summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/Android.mk1
-rw-r--r--camera/Camera.cpp16
-rw-r--r--camera/CameraParameters.cpp7
-rw-r--r--camera/ICamera.cpp36
-rw-r--r--cmds/stagefright/Android.mk6
-rw-r--r--cmds/stagefright/audioloop.cpp6
-rw-r--r--cmds/stagefright/sf2.cpp1
-rw-r--r--cmds/stagefright/stream.cpp3
-rw-r--r--drm/common/DrmInfoEvent.cpp4
-rw-r--r--drm/common/DrmSupportInfo.cpp2
-rw-r--r--drm/common/IDrmManagerService.cpp5
-rw-r--r--drm/drmserver/Android.mk1
-rw-r--r--drm/drmserver/DrmManager.cpp3
-rw-r--r--drm/drmserver/DrmManagerService.cpp29
-rw-r--r--drm/libdrmframework/Android.mk2
-rw-r--r--drm/libdrmframework/DrmManagerClient.cpp25
-rw-r--r--drm/libdrmframework/DrmManagerClientImpl.cpp114
-rw-r--r--drm/libdrmframework/include/DrmManager.h3
-rw-r--r--drm/libdrmframework/include/DrmManagerClientImpl.h18
-rw-r--r--drm/libdrmframework/include/DrmManagerService.h2
-rw-r--r--drm/libdrmframework/include/IDrmManagerService.h1
-rw-r--r--drm/libdrmframework/plugins/common/include/IDrmEngine.h1
-rw-r--r--drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk2
-rw-r--r--drm/libdrmframework/plugins/passthru/Android.mk2
-rw-r--r--include/camera/Camera.h114
-rw-r--r--include/camera/CameraHardwareInterface.h320
-rw-r--r--include/camera/CameraParameters.h99
-rw-r--r--include/camera/ICamera.h6
-rw-r--r--include/drm/DrmInfoEvent.h6
-rw-r--r--include/drm/DrmManagerClient.h21
-rw-r--r--include/drm/drm_framework_common.h29
-rw-r--r--include/media/AudioParameter.h72
-rw-r--r--include/media/AudioRecord.h15
-rw-r--r--include/media/AudioSystem.h338
-rw-r--r--include/media/AudioTrack.h7
-rw-r--r--include/media/EffectApi.h6
-rw-r--r--include/media/IAudioPolicyService.h35
-rw-r--r--include/media/IMediaMetadataRetriever.h9
-rw-r--r--include/media/IMediaPlayer.h3
-rw-r--r--include/media/IMediaPlayerClient.h2
-rw-r--r--include/media/IOMX.h1
-rw-r--r--include/media/MediaMetadataRetrieverInterface.h6
-rw-r--r--include/media/MediaPlayerInterface.h13
-rw-r--r--include/media/MediaRecorderBase.h4
-rw-r--r--include/media/MemoryLeakTrackUtil.h28
-rw-r--r--include/media/mediametadataretriever.h13
-rw-r--r--include/media/mediaplayer.h11
-rw-r--r--include/media/mediarecorder.h80
-rw-r--r--include/media/stagefright/AudioPlayer.h2
-rw-r--r--include/media/stagefright/AudioSource.h6
-rw-r--r--include/media/stagefright/CameraSource.h28
-rw-r--r--include/media/stagefright/DataSource.h6
-rw-r--r--include/media/stagefright/FileSource.h6
-rw-r--r--include/media/stagefright/HardwareAPI.h2
-rw-r--r--include/media/stagefright/MPEG4Writer.h2
-rw-r--r--include/media/stagefright/MediaDefs.h3
-rw-r--r--include/media/stagefright/MediaErrors.h12
-rw-r--r--include/media/stagefright/MetaData.h3
-rw-r--r--include/private/media/AudioTrackShared.h8
-rw-r--r--include/private/opengles/gl_context.h18
-rw-r--r--media/libeffects/lvm/lib/Android.mk4
-rw-r--r--media/libeffects/lvm/wrapper/Android.mk4
-rw-r--r--media/libeffects/visualizer/Android.mk2
-rw-r--r--media/libmedia/Android.mk15
-rw-r--r--media/libmedia/AudioEffect.cpp1
-rw-r--r--media/libmedia/AudioParameter.cpp179
-rw-r--r--media/libmedia/AudioRecord.cpp41
-rw-r--r--media/libmedia/AudioSystem.cpp361
-rw-r--r--media/libmedia/AudioTrack.cpp157
-rw-r--r--media/libmedia/IAudioPolicyService.cpp94
-rw-r--r--media/libmedia/IMediaMetadataRetriever.cpp29
-rw-r--r--media/libmedia/IMediaPlayer.cpp48
-rw-r--r--media/libmedia/IMediaPlayerClient.cpp12
-rw-r--r--media/libmedia/JetPlayer.cpp4
-rw-r--r--media/libmedia/MediaScanner.cpp7
-rw-r--r--media/libmedia/MemoryLeakTrackUtil.cpp169
-rw-r--r--media/libmedia/ToneGenerator.cpp4
-rw-r--r--media/libmedia/Visualizer.cpp4
-rw-r--r--media/libmedia/mediametadataretriever.cpp5
-rw-r--r--media/libmedia/mediaplayer.cpp33
-rw-r--r--media/libmediaplayerservice/Android.mk3
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp177
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h12
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp4
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp5
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h5
-rw-r--r--media/libmediaplayerservice/MidiFile.cpp6
-rw-r--r--media/libmediaplayerservice/MidiFile.h7
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.cpp6
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.h4
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.cpp12
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.h2
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp30
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h6
-rw-r--r--media/libmediaplayerservice/TestPlayerStub.h6
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp21
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.h14
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp12
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp8
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp21
-rw-r--r--media/libstagefright/ACodec.cpp4
-rw-r--r--media/libstagefright/AMRWriter.cpp4
-rw-r--r--media/libstagefright/AVIExtractor.cpp922
-rw-r--r--media/libstagefright/Android.mk60
-rw-r--r--media/libstagefright/AudioPlayer.cpp82
-rw-r--r--media/libstagefright/AudioSource.cpp4
-rw-r--r--media/libstagefright/AwesomePlayer.cpp248
-rw-r--r--media/libstagefright/CameraSource.cpp22
-rw-r--r--media/libstagefright/DRMExtractor.cpp18
-rw-r--r--media/libstagefright/DataSource.cpp10
-rw-r--r--media/libstagefright/FileSource.cpp6
-rw-r--r--media/libstagefright/HTTPBase.cpp45
-rw-r--r--media/libstagefright/MP3Extractor.cpp38
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp96
-rw-r--r--media/libstagefright/MPEG4Writer.cpp42
-rw-r--r--media/libstagefright/MediaDefs.cpp3
-rw-r--r--media/libstagefright/MediaExtractor.cpp3
-rw-r--r--media/libstagefright/NuCachedSource2.cpp37
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp31
-rw-r--r--media/libstagefright/OMXCodec.cpp50
-rw-r--r--media/libstagefright/SampleTable.cpp163
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp6
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp79
-rw-r--r--media/libstagefright/TimedTextPlayer.cpp252
-rw-r--r--media/libstagefright/WAVExtractor.cpp8
-rw-r--r--media/libstagefright/XINGSeeker.cpp2
-rw-r--r--media/libstagefright/chromium_http/Android.mk25
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp336
-rw-r--r--media/libstagefright/chromium_http/support.cpp461
-rw-r--r--media/libstagefright/chromium_http/support.h159
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_dec.cpp32
-rw-r--r--media/libstagefright/codecs/aacenc/Android.mk2
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c2
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/Android.mk27
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/ms.mk23
-rw-r--r--media/libstagefright/codecs/aacenc/Tools/doit.mk133
-rw-r--r--media/libstagefright/codecs/aacenc/Tools/eclair.mk172
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/makefile40
-rw-r--r--media/libstagefright/codecs/aacenc/build/ms.mk42
-rw-r--r--media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp14
-rw-r--r--media/libstagefright/codecs/amrwbenc/Android.mk2
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c2
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk24
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile56
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk24
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile53
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile53
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/makefile39
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk43
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp3
-rw-r--r--media/libstagefright/codecs/common/Android.mk2
-rw-r--r--media/libstagefright/codecs/mp3dec/MP3Decoder.cpp10
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp2
-rw-r--r--media/libstagefright/foundation/ALooper.cpp23
-rw-r--r--media/libstagefright/foundation/Android.mk2
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp36
-rw-r--r--media/libstagefright/include/AVIExtractor.h111
-rw-r--r--media/libstagefright/include/AwesomePlayer.h61
-rw-r--r--media/libstagefright/include/ChromiumHTTPDataSource.h133
-rw-r--r--media/libstagefright/include/DRMExtractor.h2
-rw-r--r--media/libstagefright/include/HTTPBase.h53
-rw-r--r--media/libstagefright/include/LiveSession.h13
-rw-r--r--media/libstagefright/include/MP3Extractor.h2
-rw-r--r--media/libstagefright/include/MPEG4Extractor.h4
-rw-r--r--media/libstagefright/include/NuCachedSource2.h11
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h25
-rw-r--r--media/libstagefright/include/SampleTable.h12
-rw-r--r--media/libstagefright/include/StagefrightMetadataRetriever.h5
-rw-r--r--media/libstagefright/include/TimedTextPlayer.h91
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp344
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.h9
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp2
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp16
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp27
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.h6
-rw-r--r--media/libstagefright/yuv/Android.mk2
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp498
-rw-r--r--services/audioflinger/A2dpAudioInterface.h138
-rw-r--r--services/audioflinger/Android.mk90
-rw-r--r--services/audioflinger/AudioDumpInterface.cpp573
-rw-r--r--services/audioflinger/AudioDumpInterface.h170
-rw-r--r--services/audioflinger/AudioFlinger.cpp543
-rw-r--r--services/audioflinger/AudioFlinger.h37
-rw-r--r--services/audioflinger/AudioHardwareGeneric.cpp411
-rw-r--r--services/audioflinger/AudioHardwareGeneric.h151
-rw-r--r--services/audioflinger/AudioHardwareInterface.cpp183
-rw-r--r--services/audioflinger/AudioHardwareStub.cpp209
-rw-r--r--services/audioflinger/AudioHardwareStub.h106
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp2286
-rw-r--r--services/audioflinger/AudioPolicyService.cpp613
-rw-r--r--services/audioflinger/AudioPolicyService.h90
-rw-r--r--services/camera/libcameraservice/Android.mk47
-rw-r--r--services/camera/libcameraservice/CameraHardwareInterface.h619
-rw-r--r--services/camera/libcameraservice/CameraService.cpp126
-rw-r--r--services/camera/libcameraservice/CameraService.h17
-rw-r--r--services/camera/tests/CameraServiceTest/Android.mk2
-rw-r--r--services/camera/tests/CameraServiceTest/CameraServiceTest.cpp8
201 files changed, 6676 insertions, 8572 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index 2f16923..b17b3d2 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -13,7 +13,6 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder \
libhardware \
- libsurfaceflinger_client \
libui \
libgui
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index e288312..5eb48da 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -205,22 +205,6 @@ status_t Camera::startPreview()
return c->startPreview();
}
-int32_t Camera::getNumberOfVideoBuffers() const
-{
- LOGV("getNumberOfVideoBuffers");
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> Camera::getVideoBuffer(int32_t index) const
-{
- LOGV("getVideoBuffer: %d", index);
- sp <ICamera> c = mCamera;
- if (c == 0) return 0;
- return c->getVideoBuffer(index);
-}
-
status_t Camera::storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s",
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 0fd79a4..4f3da40 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -59,6 +59,8 @@ const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas";
+const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas";
const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
@@ -66,6 +68,10 @@ const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensatio
const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation";
const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation";
const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = "auto-exposure-lock";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[] = "auto-exposure-lock-supported";
+const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas";
+const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas";
const char CameraParameters::KEY_ZOOM[] = "zoom";
const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom";
const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
@@ -78,6 +84,7 @@ const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
const char CameraParameters::TRUE[] = "true";
+const char CameraParameters::FALSE[] = "false";
const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
// Values for white balance settings.
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 931b57d..5f6e5ef 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -46,8 +46,6 @@ enum {
STOP_RECORDING,
RECORDING_ENABLED,
RELEASE_RECORDING_FRAME,
- GET_NUM_VIDEO_BUFFERS,
- GET_VIDEO_BUFFER,
STORE_META_DATA_IN_BUFFERS,
};
@@ -149,27 +147,6 @@ public:
remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
}
- int32_t getNumberOfVideoBuffers() const
- {
- LOGV("getNumberOfVideoBuffers");
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- remote()->transact(GET_NUM_VIDEO_BUFFERS, data, &reply);
- return reply.readInt32();
- }
-
- sp<IMemory> getVideoBuffer(int32_t index) const
- {
- LOGV("getVideoBuffer: %d", index);
- Parcel data, reply;
- data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
- data.writeInt32(index);
- remote()->transact(GET_VIDEO_BUFFER, data, &reply);
- sp<IMemory> mem = interface_cast<IMemory>(
- reply.readStrongBinder());
- return mem;
- }
-
status_t storeMetaDataInBuffers(bool enabled)
{
LOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -355,19 +332,6 @@ status_t BnCamera::onTransact(
releaseRecordingFrame(mem);
return NO_ERROR;
} break;
- case GET_NUM_VIDEO_BUFFERS: {
- LOGV("GET_NUM_VIDEO_BUFFERS");
- CHECK_INTERFACE(ICamera, data, reply);
- reply->writeInt32(getNumberOfVideoBuffers());
- return NO_ERROR;
- } break;
- case GET_VIDEO_BUFFER: {
- LOGV("GET_VIDEO_BUFFER");
- CHECK_INTERFACE(ICamera, data, reply);
- int32_t index = data.readInt32();
- reply->writeStrongBinder(getVideoBuffer(index)->asBinder());
- return NO_ERROR;
- } break;
case STORE_META_DATA_IN_BUFFERS: {
LOGV("STORE_META_DATA_IN_BUFFERS");
CHECK_INTERFACE(ICamera, data, reply);
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 1b13dd9..e9642f7 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libutils libbinder libstagefright_foundation \
- libskia libsurfaceflinger_client libgui
+ libskia libgui
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
@@ -107,7 +107,7 @@ LOCAL_SRC_FILES:= \
stream.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright liblog libutils libbinder libsurfaceflinger_client \
+ libstagefright liblog libutils libbinder libgui \
libstagefright_foundation libmedia
LOCAL_C_INCLUDES:= \
@@ -132,7 +132,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libstagefright_foundation \
- libmedia libsurfaceflinger_client libcutils libui
+ libmedia libgui libcutils libui
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 8733662..ceb254f 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -11,6 +11,8 @@
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+#include <hardware/audio.h>
+
using namespace android;
int main() {
@@ -31,8 +33,8 @@ int main() {
AUDIO_SOURCE_DEFAULT,
kSampleRate,
kNumChannels == 1
- ? AudioSystem::CHANNEL_IN_MONO
- : AudioSystem::CHANNEL_IN_STEREO);
+ ? AUDIO_CHANNEL_IN_MONO
+ : AUDIO_CHANNEL_IN_STEREO);
#endif
sp<MetaData> meta = new MetaData;
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index c1d0803..289665f 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -543,7 +543,6 @@ int main(int argc, char **argv) {
CHECK_EQ(composerClient->initCheck(), (status_t)OK);
control = composerClient->createSurface(
- getpid(),
String8("A Surface"),
0,
1280,
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index bb84bd1..f780afb 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -107,7 +107,7 @@ struct MyClient : public BnMediaPlayerClient {
: mEOS(false) {
}
- virtual void notify(int msg, int ext1, int ext2) {
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
Mutex::Autolock autoLock(mLock);
if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) {
@@ -149,7 +149,6 @@ int main(int argc, char **argv) {
sp<SurfaceControl> control =
composerClient->createSurface(
- getpid(),
String8("A Surface"),
0,
1280,
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
index 8d115a8..27a5a2d 100644
--- a/drm/common/DrmInfoEvent.cpp
+++ b/drm/common/DrmInfoEvent.cpp
@@ -19,7 +19,7 @@
using namespace android;
-DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8& message)
+DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8 message)
: mUniqueId(uniqueId),
mInfoType(infoType),
mMessage(message) {
@@ -34,7 +34,7 @@ int DrmInfoEvent::getType() const {
return mInfoType;
}
-const String8& DrmInfoEvent::getMessage() const {
+const String8 DrmInfoEvent::getMessage() const {
return mMessage;
}
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index c0bff0e..3dee435 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -15,6 +15,7 @@
*/
#include <drm/DrmSupportInfo.h>
+#include <strings.h>
using namespace android;
@@ -152,4 +153,3 @@ String8& DrmSupportInfo::MimeTypeIterator::next() {
mIndex++;
return value;
}
-
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 346934b..c37b4f8 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -650,11 +650,6 @@ status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* d
remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
- if (NULL != decryptHandle->decryptInfo) {
- LOGV("deleting decryptInfo");
- delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
- }
- delete decryptHandle; decryptHandle = NULL;
return reply.readInt32();
}
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index f94f9a3..e3cd44f 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES:= \
DrmManagerService.cpp
LOCAL_SHARED_LIBRARIES := \
+ libmedia \
libutils \
libbinder
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1eee5f2..1809619 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -37,7 +37,6 @@
using namespace android;
-Vector<int> DrmManager::mUniqueIdVector;
const String8 DrmManager::EMPTY_STRING("");
DrmManager::DrmManager() :
@@ -102,6 +101,7 @@ status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
if (NULL != info) {
mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+ delete info;
}
}
}
@@ -179,6 +179,7 @@ status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath)
DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
mSupportInfoToPlugInIdMap.add(*info, absolutePath);
+ delete info;
return DRM_NO_ERROR;
}
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 0901a44..583669e 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
+#include <media/MemoryLeakTrackUtil.h>
#include <errno.h>
#include <utils/threads.h>
@@ -256,3 +257,31 @@ ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
}
+status_t DrmManagerService::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump DrmManagerService from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ } else {
+#if DRM_MEMORY_LEAK_TRACK
+ bool dumpMem = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ }
+ }
+ if (dumpMem) {
+ dumpMemoryAddresses(fd);
+ }
+#endif
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 99133ba..f1526a4 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -40,7 +40,7 @@ LOCAL_C_INCLUDES += \
$(TOP)/frameworks/base/drm/libdrmframework/include \
$(TOP)/frameworks/base/include
-LOCAL_PRELINK_MODULE := false
+
LOCAL_MODULE_TAGS := optional
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index c1f382a..b50199f 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -76,12 +76,13 @@ int DrmManagerClient::checkRightsStatus(const String8& path, int action) {
return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
}
-status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+status_t DrmManagerClient::consumeRights(
+ sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
}
status_t DrmManagerClient::setPlaybackStatus(
- DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
return mDrmManagerClientImpl
->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
}
@@ -115,37 +116,39 @@ status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSu
return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
}
-DecryptHandle* DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
}
-DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(const char* uri) {
return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri);
}
-status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
+status_t DrmManagerClient::closeDecryptSession(sp<DecryptHandle> &decryptHandle) {
return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
}
status_t DrmManagerClient::initializeDecryptUnit(
- DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
return mDrmManagerClientImpl->initializeDecryptUnit(
mUniqueId, decryptHandle, decryptUnitId, headerInfo);
}
status_t DrmManagerClient::decrypt(
- DecryptHandle* decryptHandle, int decryptUnitId,
- const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
return mDrmManagerClientImpl->decrypt(
mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
}
-status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
- return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
+status_t DrmManagerClient::finalizeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+ return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId,
+ decryptHandle, decryptUnitId);
}
ssize_t DrmManagerClient::pread(
- DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
+ sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
}
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 9c7fed3..a57dd98 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -81,14 +81,16 @@ void DrmManagerClientImpl::removeClient(int uniqueId) {
}
status_t DrmManagerClientImpl::setOnInfoListener(
- int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ int uniqueId,
+ const sp<DrmManagerClient::OnInfoListener>& infoListener) {
Mutex::Autolock _l(mLock);
mOnInfoListener = infoListener;
return getDrmManagerService()->setDrmServiceListener(uniqueId,
(NULL != infoListener.get()) ? this : NULL);
}
-status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+status_t DrmManagerClientImpl::installDrmEngine(
+ int uniqueId, const String8& drmEngineFile) {
status_t status = DRM_ERROR_UNKNOWN;
if (EMPTY_STRING != drmEngineFile) {
status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
@@ -100,7 +102,8 @@ DrmConstraints* DrmManagerClientImpl::getConstraints(
int uniqueId, const String8* path, const int action) {
DrmConstraints *drmConstraints = NULL;
if ((NULL != path) && (EMPTY_STRING != *path)) {
- drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action);
+ drmConstraints =
+ getDrmManagerService()->getConstraints(uniqueId, path, action);
}
return drmConstraints;
}
@@ -113,7 +116,8 @@ DrmMetadata* DrmManagerClientImpl::getMetadata(int uniqueId, const String8* path
return drmMetadata;
}
-bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+bool DrmManagerClientImpl::canHandle(
+ int uniqueId, const String8& path, const String8& mimeType) {
bool retCode = false;
if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
@@ -121,7 +125,8 @@ bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const St
return retCode;
}
-DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(
+ int uniqueId, const DrmInfo* drmInfo) {
DrmInfoStatus *drmInfoStatus = NULL;
if (NULL != drmInfo) {
drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
@@ -129,7 +134,8 @@ DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo*
return drmInfoStatus;
}
-DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(
+ int uniqueId, const DrmInfoRequest* drmInfoRequest) {
DrmInfo* drmInfo = NULL;
if (NULL != drmInfoRequest) {
drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
@@ -140,13 +146,12 @@ DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest
status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
const String8& rightsPath, const String8& contentPath) {
status_t status = DRM_ERROR_UNKNOWN;
- if (EMPTY_STRING != contentPath) {
- status = getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath);
- }
- return status;
+ return getDrmManagerService()->saveRights(
+ uniqueId, drmRights, rightsPath, contentPath);
}
-String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) {
+String8 DrmManagerClientImpl::getOriginalMimeType(
+ int uniqueId, const String8& path) {
String8 mimeType = EMPTY_STRING;
if (EMPTY_STRING != path) {
mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
@@ -158,7 +163,8 @@ int DrmManagerClientImpl::getDrmObjectType(
int uniqueId, const String8& path, const String8& mimeType) {
int drmOjectType = DrmObjectType::UNKNOWN;
if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
- drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+ drmOjectType =
+ getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
}
return drmOjectType;
}
@@ -167,35 +173,41 @@ int DrmManagerClientImpl::checkRightsStatus(
int uniqueId, const String8& path, int action) {
int rightsStatus = RightsStatus::RIGHTS_INVALID;
if (EMPTY_STRING != path) {
- rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+ rightsStatus =
+ getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
}
return rightsStatus;
}
status_t DrmManagerClientImpl::consumeRights(
- int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int action, bool reserve) {
status_t status = DRM_ERROR_UNKNOWN;
- if (NULL != decryptHandle) {
- status = getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve);
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->consumeRights(
+ uniqueId, decryptHandle.get(), action, reserve);
}
return status;
}
status_t DrmManagerClientImpl::setPlaybackStatus(
- int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int playbackStatus, int64_t position) {
status_t status = DRM_ERROR_UNKNOWN;
- if (NULL != decryptHandle) {
+ if (NULL != decryptHandle.get()) {
status = getDrmManagerService()->setPlaybackStatus(
- uniqueId, decryptHandle, playbackStatus, position);
+ uniqueId, decryptHandle.get(), playbackStatus, position);
}
return status;
}
bool DrmManagerClientImpl::validateAction(
- int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
bool retCode = false;
if (EMPTY_STRING != path) {
- retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description);
+ retCode = getDrmManagerService()->validateAction(
+ uniqueId, path, action, description);
}
return retCode;
}
@@ -212,7 +224,8 @@ status_t DrmManagerClientImpl::removeAllRights(int uniqueId) {
return getDrmManagerService()->removeAllRights(uniqueId);
}
-int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+int DrmManagerClientImpl::openConvertSession(
+ int uniqueId, const String8& mimeType) {
int retCode = INVALID_VALUE;
if (EMPTY_STRING != mimeType) {
retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
@@ -224,12 +237,14 @@ DrmConvertedStatus* DrmManagerClientImpl::convertData(
int uniqueId, int convertId, const DrmBuffer* inputData) {
DrmConvertedStatus* drmConvertedStatus = NULL;
if (NULL != inputData) {
- drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+ drmConvertedStatus =
+ getDrmManagerService()->convertData(uniqueId, convertId, inputData);
}
return drmConvertedStatus;
}
-DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(
+ int uniqueId, int convertId) {
return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
}
@@ -237,17 +252,19 @@ status_t DrmManagerClientImpl::getAllSupportInfo(
int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
status_t status = DRM_ERROR_UNKNOWN;
if ((NULL != drmSupportInfoArray) && (NULL != length)) {
- status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+ status = getDrmManagerService()->getAllSupportInfo(
+ uniqueId, length, drmSupportInfoArray);
}
return status;
}
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
int uniqueId, int fd, off64_t offset, off64_t length) {
return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
}
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) {
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
+ int uniqueId, const char* uri) {
DecryptHandle* handle = NULL;
if (NULL != uri) {
handle = getDrmManagerService()->openDecryptSession(uniqueId, uri);
@@ -255,50 +272,57 @@ DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char
return handle;
}
-status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+status_t DrmManagerClientImpl::closeDecryptSession(
+ int uniqueId, sp<DecryptHandle> &decryptHandle) {
status_t status = DRM_ERROR_UNKNOWN;
- if (NULL != decryptHandle) {
- status = getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle);
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->closeDecryptSession(
+ uniqueId, decryptHandle.get());
}
return status;
}
-status_t DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
- int decryptUnitId, const DrmBuffer* headerInfo) {
+status_t DrmManagerClientImpl::initializeDecryptUnit(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
status_t status = DRM_ERROR_UNKNOWN;
- if ((NULL != decryptHandle) && (NULL != headerInfo)) {
+ if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) {
status = getDrmManagerService()->initializeDecryptUnit(
- uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ uniqueId, decryptHandle.get(), decryptUnitId, headerInfo);
}
return status;
}
-status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle,
- int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+status_t DrmManagerClientImpl::decrypt(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer,
+ DrmBuffer** decBuffer, DrmBuffer* IV) {
status_t status = DRM_ERROR_UNKNOWN;
- if ((NULL != decryptHandle) && (NULL != encBuffer)
+ if ((NULL != decryptHandle.get()) && (NULL != encBuffer)
&& (NULL != decBuffer) && (NULL != *decBuffer)) {
status = getDrmManagerService()->decrypt(
- uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+ uniqueId, decryptHandle.get(), decryptUnitId,
+ encBuffer, decBuffer, IV);
}
return status;
}
status_t DrmManagerClientImpl::finalizeDecryptUnit(
- int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
status_t status = DRM_ERROR_UNKNOWN;
- if (NULL != decryptHandle) {
- status
- = getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->finalizeDecryptUnit(
+ uniqueId, decryptHandle.get(), decryptUnitId);
}
return status;
}
-ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle,
+ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
void* buffer, ssize_t numBytes, off64_t offset) {
ssize_t retCode = INVALID_VALUE;
- if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) {
- retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) {
+ retCode = getDrmManagerService()->pread(
+ uniqueId, decryptHandle.get(), buffer, numBytes, offset);
}
return retCode;
}
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index c7276f9..af2c2a8 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -30,7 +30,6 @@ class IDrmManager;
class DrmRegistrationInfo;
class DrmUnregistrationInfo;
class DrmRightsAcquisitionInfo;
-class DrmContentIds;
class DrmConstraints;
class DrmMetadata;
class DrmRights;
@@ -141,7 +140,7 @@ private:
bool canHandle(int uniqueId, const String8& path);
private:
- static Vector<int> mUniqueIdVector;
+ Vector<int> mUniqueIdVector;
static const String8 EMPTY_STRING;
int mDecryptSessionId;
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 429e4c3..564896b 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -189,7 +189,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+ status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
/**
* Informs the DRM engine about the playback actions performed on the DRM files.
@@ -203,7 +203,7 @@ public:
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
status_t setPlaybackStatus(
- int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+ int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
/**
* Validates whether an action on the DRM content is allowed or not.
@@ -303,7 +303,7 @@ public:
* @return
* Handle for the decryption session
*/
- DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
+ sp<DecryptHandle> openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
/**
* Open the decrypt session to decrypt the given protected content
@@ -313,7 +313,7 @@ public:
* @return
* Handle for the decryption session
*/
- DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+ sp<DecryptHandle> openDecryptSession(int uniqueId, const char* uri);
/**
* Close the decrypt session for the given handle
@@ -323,7 +323,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+ status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
/**
* Initialize decryption for the given unit of the protected content
@@ -335,7 +335,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
int decryptUnitId, const DrmBuffer* headerInfo);
/**
@@ -355,7 +355,7 @@ public:
* DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
* DRM_ERROR_DECRYPT for failure.
*/
- status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
/**
@@ -367,7 +367,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+ status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
/**
* Reads the specified number of bytes from an open DRM file.
@@ -380,7 +380,7 @@ public:
*
* @return Number of bytes read. Returns -1 for Failure.
*/
- ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
void* buffer, ssize_t numBytes, off64_t offset);
/**
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index d0a0db7..227496a 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -115,6 +115,8 @@ public:
ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
void* buffer, ssize_t numBytes, off64_t offset);
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
private:
DrmManager* mDrmManager;
};
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 2424ea5..7727e55 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -25,7 +25,6 @@
namespace android {
-class DrmContentIds;
class DrmConstraints;
class DrmMetadata;
class DrmRights;
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
index d05c24f..77460f6 100644
--- a/drm/libdrmframework/plugins/common/include/IDrmEngine.h
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -21,7 +21,6 @@
namespace android {
-class DrmContentIds;
class DrmConstraints;
class DrmMetadata;
class DrmRights;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index af67aa3..9805a40 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -47,7 +47,7 @@ LOCAL_STATIC_LIBRARIES := \
libfwdlock-converter \
libfwdlock-decoder
-LOCAL_PRELINK_MODULE := false
+
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index 7856d37..be18b64 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -32,7 +32,7 @@ else
LOCAL_SHARED_LIBRARIES += libdl
endif
-LOCAL_PRELINK_MODULE := false
+
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/base/drm/libdrmframework/include \
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index f3c8f64..7106bfa 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -20,122 +20,28 @@
#include <utils/Timers.h>
#include <camera/ICameraClient.h>
#include <gui/ISurfaceTexture.h>
+#include <system/camera.h>
namespace android {
-/*
- * A set of bit masks for specifying how the received preview frames are
- * handled before the previewCallback() call.
- *
- * The least significant 3 bits of an "int" value are used for this purpose:
- *
- * ..... 0 0 0
- * ^ ^ ^
- * | | |---------> determine whether the callback is enabled or not
- * | |-----------> determine whether the callback is one-shot or not
- * |-------------> determine whether the frame is copied out or not
- *
- * WARNING:
- * When a frame is sent directly without copying, it is the frame receiver's
- * responsiblity to make sure that the frame data won't get corrupted by
- * subsequent preview frames filled by the camera. This flag is recommended
- * only when copying out data brings significant performance price and the
- * handling/processing of the received frame data is always faster than
- * the preview frame rate so that data corruption won't occur.
- *
- * For instance,
- * 1. 0x00 disables the callback. In this case, copy out and one shot bits
- * are ignored.
- * 2. 0x01 enables a callback without copying out the received frames. A
- * typical use case is the Camcorder application to avoid making costly
- * frame copies.
- * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical
- * use case is the Camera application.
- * 4. 0x07 is enabling a callback with frame copied out only once. A typical use
- * case is the Barcode scanner application.
- */
-#define FRAME_CALLBACK_FLAG_ENABLE_MASK 0x01
-#define FRAME_CALLBACK_FLAG_ONE_SHOT_MASK 0x02
-#define FRAME_CALLBACK_FLAG_COPY_OUT_MASK 0x04
-
-// Typical use cases
-#define FRAME_CALLBACK_FLAG_NOOP 0x00
-#define FRAME_CALLBACK_FLAG_CAMCORDER 0x01
-#define FRAME_CALLBACK_FLAG_CAMERA 0x05
-#define FRAME_CALLBACK_FLAG_BARCODE_SCANNER 0x07
-
-// msgType in notifyCallback and dataCallback functions
-enum {
- CAMERA_MSG_ERROR = 0x0001,
- CAMERA_MSG_SHUTTER = 0x0002,
- CAMERA_MSG_FOCUS = 0x0004,
- CAMERA_MSG_ZOOM = 0x0008,
- CAMERA_MSG_PREVIEW_FRAME = 0x0010,
- CAMERA_MSG_VIDEO_FRAME = 0x0020,
- CAMERA_MSG_POSTVIEW_FRAME = 0x0040,
- CAMERA_MSG_RAW_IMAGE = 0x0080,
- CAMERA_MSG_COMPRESSED_IMAGE = 0x0100,
- CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200,
- CAMERA_MSG_ALL_MSGS = 0xFFFF
-};
-
-// cmdType in sendCommand functions
-enum {
- CAMERA_CMD_START_SMOOTH_ZOOM = 1,
- CAMERA_CMD_STOP_SMOOTH_ZOOM = 2,
- // Set the clockwise rotation of preview display (setPreviewDisplay) in
- // degrees. This affects the preview frames and the picture displayed after
- // snapshot. This method is useful for portrait mode applications. Note that
- // preview display of front-facing cameras is flipped horizontally before
- // the rotation, that is, the image is reflected along the central vertical
- // axis of the camera sensor. So the users can see themselves as looking
- // into a mirror.
- //
- // This does not affect the order of byte array of CAMERA_MSG_PREVIEW_FRAME,
- // CAMERA_MSG_VIDEO_FRAME, CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE,
- // or CAMERA_MSG_COMPRESSED_IMAGE. This is not allowed to be set during
- // preview.
- CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
-
- // cmdType to disable/enable shutter sound.
- // In sendCommand passing arg1 = 0 will disable,
- // while passing arg1 = 1 will enable the shutter sound.
- CAMERA_CMD_ENABLE_SHUTTER_SOUND = 4,
-
- // cmdType to play recording sound.
- CAMERA_CMD_PLAY_RECORDING_SOUND = 5,
-};
-
-// camera fatal errors
-enum {
- CAMERA_ERROR_UNKNOWN = 1,
- CAMERA_ERROR_SERVER_DIED = 100
-};
-
-enum {
- CAMERA_FACING_BACK = 0, /* The facing of the camera is opposite to that of the screen. */
- CAMERA_FACING_FRONT = 1 /* The facing of the camera is the same as that of the screen. */
-};
-
struct CameraInfo {
-
/**
- * The direction that the camera faces to. It should be
- * CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
+ * The direction that the camera faces to. It should be CAMERA_FACING_BACK
+ * or CAMERA_FACING_FRONT.
*/
int facing;
/**
* The orientation of the camera image. The value is the angle that the
- * camera image needs to be rotated clockwise so it shows correctly on
- * the display in its natural orientation. It should be 0, 90, 180, or 270.
+ * camera image needs to be rotated clockwise so it shows correctly on the
+ * display in its natural orientation. It should be 0, 90, 180, or 270.
*
* For example, suppose a device has a naturally tall screen. The
* back-facing camera sensor is mounted in landscape. You are looking at
* the screen. If the top side of the camera sensor is aligned with the
* right edge of the screen in natural orientation, the value should be
- * 90. If the top side of a front-facing camera sensor is aligned with
- * the right of the screen, the value should be 270.
+ * 90. If the top side of a front-facing camera sensor is aligned with the
+ * right of the screen, the value should be 270.
*/
int orientation;
};
@@ -219,12 +125,6 @@ public:
// send command to camera driver
status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
- // return the total number of available video buffers.
- int32_t getNumberOfVideoBuffers() const;
-
- // return the individual video buffer corresponding to the given index.
- sp<IMemory> getVideoBuffer(int32_t index) const;
-
// tell camera hal to store meta data or real YUV in video buffers.
status_t storeMetaDataInBuffers(bool enabled);
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
deleted file mode 100644
index 86bd849..0000000
--- a/include/camera/CameraHardwareInterface.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2008 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 ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
-#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
-
-#include <binder/IMemory.h>
-#include <ui/egl/android_natives.h>
-#include <utils/RefBase.h>
-#include <surfaceflinger/ISurface.h>
-#include <ui/android_native_buffer.h>
-#include <ui/GraphicBuffer.h>
-#include <camera/Camera.h>
-#include <camera/CameraParameters.h>
-
-namespace android {
-
-/**
- * The size of image for display.
- */
-typedef struct image_rect_struct
-{
- uint32_t width; /* Image width */
- uint32_t height; /* Image height */
-} image_rect_type;
-
-
-typedef void (*notify_callback)(int32_t msgType,
- int32_t ext1,
- int32_t ext2,
- void* user);
-
-typedef void (*data_callback)(int32_t msgType,
- const sp<IMemory>& dataPtr,
- void* user);
-
-typedef void (*data_callback_timestamp)(nsecs_t timestamp,
- int32_t msgType,
- const sp<IMemory>& dataPtr,
- void* user);
-
-/**
- * CameraHardwareInterface.h defines the interface to the
- * camera hardware abstraction layer, used for setting and getting
- * parameters, live previewing, and taking pictures.
- *
- * It is a referenced counted interface with RefBase as its base class.
- * CameraService calls openCameraHardware() to retrieve a strong pointer to the
- * instance of this interface and may be called multiple times. The
- * following steps describe a typical sequence:
- *
- * -# After CameraService calls openCameraHardware(), getParameters() and
- * setParameters() are used to initialize the camera instance.
- * CameraService calls getPreviewHeap() to establish access to the
- * preview heap so it can be registered with SurfaceFlinger for
- * efficient display updating while in preview mode.
- * -# startPreview() is called. The camera instance then periodically
- * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time
- * a new preview frame is available. If data callback code needs to use
- * this memory after returning, it must copy the data.
- *
- * Prior to taking a picture, CameraService calls autofocus(). When auto
- * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification,
- * which informs the application whether focusing was successful. The camera instance
- * only sends this message once and it is up to the application to call autoFocus()
- * again if refocusing is desired.
- *
- * CameraService calls takePicture() to request the camera instance take a
- * picture. At this point, if a shutter, postview, raw, and/or compressed callback
- * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME,
- * any memory provided in a data callback must be copied if it's needed after returning.
- */
-class CameraHardwareInterface : public virtual RefBase {
-public:
- virtual ~CameraHardwareInterface() { }
-
- /** Set the ANativeWindow to which preview frames are sent */
- virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf) = 0;
-
- /** Return the IMemoryHeap for the raw image heap */
- virtual sp<IMemoryHeap> getRawHeap() const = 0;
-
- /** Set the notification and data callbacks */
- virtual void setCallbacks(notify_callback notify_cb,
- data_callback data_cb,
- data_callback_timestamp data_cb_timestamp,
- void* user) = 0;
-
- /**
- * The following three functions all take a msgtype,
- * which is a bitmask of the messages defined in
- * include/ui/Camera.h
- */
-
- /**
- * Enable a message, or set of messages.
- */
- virtual void enableMsgType(int32_t msgType) = 0;
-
- /**
- * Disable a message, or a set of messages.
- *
- * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera hal
- * should not rely on its client to call releaseRecordingFrame() to release
- * video recording frames sent out by the cameral hal before and after the
- * disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera hal clients must not
- * modify/access any video recording frame after calling
- * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
- */
- virtual void disableMsgType(int32_t msgType) = 0;
-
- /**
- * Query whether a message, or a set of messages, is enabled.
- * Note that this is operates as an AND, if any of the messages
- * queried are off, this will return false.
- */
- virtual bool msgTypeEnabled(int32_t msgType) = 0;
-
- /**
- * Start preview mode.
- */
- virtual status_t startPreview() = 0;
-
- /**
- * Stop a previously started preview.
- */
- virtual void stopPreview() = 0;
-
- /**
- * Returns true if preview is enabled.
- */
- virtual bool previewEnabled() = 0;
-
- /**
- * Retrieve the total number of available buffers from camera hal for passing
- * video frame data in a recording session. Must be called again if a new
- * recording session is started.
- *
- * This method should be called after startRecording(), since
- * the some camera hal may choose to allocate the video buffers only after
- * recording is started.
- *
- * Some camera hal may not implement this method, and 0 can be returned to
- * indicate that this feature is not available.
- *
- * @return the number of video buffers that camera hal makes available.
- * Zero (0) is returned to indicate that camera hal does not support
- * this feature.
- */
- virtual int32_t getNumberOfVideoBuffers() const { return 0; }
-
- /**
- * Retrieve the video buffer corresponding to the given index in a
- * recording session. Must be called again if a new recording session
- * is started.
- *
- * It allows a client to retrieve all video buffers that camera hal makes
- * available to passing video frame data by calling this method with all
- * valid index values. The valid index value ranges from 0 to n, where
- * n = getNumberOfVideoBuffers() - 1. With an index outside of the valid
- * range, 0 must be returned. This method should be called after
- * startRecording().
- *
- * The video buffers should NOT be modified/released by camera hal
- * until stopRecording() is called and all outstanding video buffers
- * previously sent out via CAMERA_MSG_VIDEO_FRAME have been released
- * via releaseVideoBuffer().
- *
- * @param index an index to retrieve the corresponding video buffer.
- *
- * @return the video buffer corresponding to the given index.
- */
- virtual sp<IMemory> getVideoBuffer(int32_t index) const { return 0; }
-
- /**
- * Request the camera hal to store meta data or real YUV data in
- * the video buffers send out via CAMERA_MSG_VIDEO_FRRAME for a
- * recording session. If it is not called, the default camera
- * hal behavior is to store real YUV data in the video buffers.
- *
- * This method should be called before startRecording() in order
- * to be effective.
- *
- * If meta data is stored in the video buffers, it is up to the
- * receiver of the video buffers to interpret the contents and
- * to find the actual frame data with the help of the meta data
- * in the buffer. How this is done is outside of the scope of
- * this method.
- *
- * Some camera hal may not support storing meta data in the video
- * buffers, but all camera hal should support storing real YUV data
- * in the video buffers. If the camera hal does not support storing
- * the meta data in the video buffers when it is requested to do
- * do, INVALID_OPERATION must be returned. It is very useful for
- * the camera hal to pass meta data rather than the actual frame
- * data directly to the video encoder, since the amount of the
- * uncompressed frame data can be very large if video size is large.
- *
- * @param enable if true to instruct the camera hal to store
- * meta data in the video buffers; false to instruct
- * the camera hal to store real YUV data in the video
- * buffers.
- *
- * @return OK on success.
- */
- virtual status_t storeMetaDataInBuffers(bool enable) {
- return enable? INVALID_OPERATION: OK;
- }
-
- /**
- * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME
- * message is sent with the corresponding frame. Every record frame must be released
- * by a cameral hal client via releaseRecordingFrame() before the client calls
- * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
- * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's responsibility
- * to manage the life-cycle of the video recording frames, and the client must
- * not modify/access any video recording frames.
- */
- virtual status_t startRecording() = 0;
-
- /**
- * Stop a previously started recording.
- */
- virtual void stopRecording() = 0;
-
- /**
- * Returns true if recording is enabled.
- */
- virtual bool recordingEnabled() = 0;
-
- /**
- * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
- *
- * It is camera hal client's responsibility to release video recording
- * frames sent out by the camera hal before the camera hal receives
- * a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives
- * the call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's
- * responsibility of managing the life-cycle of the video recording
- * frames.
- */
- virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
-
- /**
- * Start auto focus, the notification callback routine is called
- * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus()
- * will be called again if another auto focus is needed.
- */
- virtual status_t autoFocus() = 0;
-
- /**
- * Cancels auto-focus function. If the auto-focus is still in progress,
- * this function will cancel it. Whether the auto-focus is in progress
- * or not, this function will return the focus position to the default.
- * If the camera does not support auto-focus, this is a no-op.
- */
- virtual status_t cancelAutoFocus() = 0;
-
- /**
- * Take a picture.
- */
- virtual status_t takePicture() = 0;
-
- /**
- * Cancel a picture that was started with takePicture. Calling this
- * method when no picture is being taken is a no-op.
- */
- virtual status_t cancelPicture() = 0;
-
- /**
- * Set the camera parameters. This returns BAD_VALUE if any parameter is
- * invalid or not supported. */
- virtual status_t setParameters(const CameraParameters& params) = 0;
-
- /** Return the camera parameters. */
- virtual CameraParameters getParameters() const = 0;
-
- /**
- * Send command to camera driver.
- */
- virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
-
- /**
- * Release the hardware resources owned by this object. Note that this is
- * *not* done in the destructor.
- */
- virtual void release() = 0;
-
- /**
- * Dump state of the camera hardware
- */
- virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
-};
-
-/**
- * The functions need to be provided by the camera HAL.
- *
- * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
- * and openCameraHardware() is 0 to N-1.
- */
-extern "C" int HAL_getNumberOfCameras();
-extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
-/* HAL should return NULL if it fails to open camera hardware. */
-extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId);
-
-}; // namespace android
-
-#endif
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index da2f049..513239f 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -247,6 +247,45 @@ public:
// Supported focus modes.
// Example value: "auto,macro,fixed". Read only.
static const char KEY_SUPPORTED_FOCUS_MODES[];
+ // The maximum number of focus areas supported. This is the maximum length
+ // of KEY_FOCUS_AREAS.
+ // Example value: "0" or "2". Read only.
+ static const char KEY_MAX_NUM_FOCUS_AREAS[];
+ // Current focus areas.
+ //
+ // Before accessing this parameter, apps should check
+ // KEY_MAX_NUM_FOCUS_AREAS first to know the maximum number of focus areas
+ // first. If the value is 0, focus area is not supported.
+ //
+ // Each focus area is a five-element int array. The first four elements are
+ // the rectangle of the area (left, top, right, bottom). The direction is
+ // relative to the sensor orientation, that is, what the sensor sees. The
+ // direction is not affected by the rotation or mirroring of
+ // CAMERA_CMD_SET_DISPLAY_ORIENTATION. Coordinates range from -1000 to 1000.
+ // (-1000,-1000) is the upper left point. (1000, 1000) is the lower right
+ // point. The length and width of focus areas cannot be 0 or negative.
+ //
+ // The fifth element is the weight. Values for weight must range from 1 to
+ // 1000. The weight should be interpreted as a per-pixel weight - all
+ // pixels in the area have the specified weight. This means a small area
+ // with the same weight as a larger area will have less influence on the
+ // focusing than the larger area. Focus areas can partially overlap and the
+ // driver will add the weights in the overlap region.
+ //
+ // A special case of single focus area (0,0,0,0,0) means driver to decide
+ // the focus area. For example, the driver may use more signals to decide
+ // focus areas and change them dynamically. Apps can set (0,0,0,0,0) if they
+ // want the driver to decide focus areas.
+ //
+ // Focus areas are relative to the current field of view (KEY_ZOOM). No
+ // matter what the zoom level is, (-1000,-1000) represents the top of the
+ // currently visible camera frame. The focus area cannot be set to be
+ // outside the current field of view, even when using zoom.
+ //
+ // Focus area only has effect if the current focus mode is FOCUS_MODE_AUTO,
+ // FOCUS_MODE_MACRO, or FOCUS_MODE_CONTINOUS_VIDEO.
+ // Example value: "(-10,-10,0,0,300),(0,0,10,10,700)". Read/write.
+ static const char KEY_FOCUS_AREAS[];
// Focal length in millimeter.
// Example value: "4.31". Read only.
static const char KEY_FOCAL_LENGTH[];
@@ -270,6 +309,65 @@ public:
// 0.3333, EV is -2.
// Example value: "0.333333333" or "0.5". Read only.
static const char KEY_EXPOSURE_COMPENSATION_STEP[];
+ // The state of the auto-exposure lock. "true" means that auto-exposure is
+ // locked to its current value and will not change. "false" means the
+ // auto-exposure routine is free to change exposure settings. Changing
+ // exposure compensation settings will still affect the exposure settings
+ // while auto-exposure is locked. Stopping preview or taking a still image
+ // will release the lock. However, the lock can be re-enabled prior to
+ // preview being re-started, to keep the exposure values from the previous
+ // lock. In conjunction with exposure compensation, this allows for
+ // capturing multi-exposure brackets with known relative exposure
+ // values. Locking auto-exposure after open but before the first cal to
+ // startPreview may result in severly over- or under-exposed images. The
+ // driver may independently enable the AE lock after auto-focus
+ // completes. If it does so, this key must have its value updated to reflect
+ // the lock's existence. Applications are free to release such a lock, to
+ // re-enable AE without restarting preview.
+ static const char KEY_AUTO_EXPOSURE_LOCK[];
+ // Whether locking the auto-exposure is supported. "true" means it is, and
+ // "false" or this key not existing means it is not supported.
+ static const char KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[];
+ // The maximum number of metering areas supported. This is the maximum
+ // length of KEY_METERING_AREAS.
+ // Example value: "0" or "2". Read only.
+ static const char KEY_MAX_NUM_METERING_AREAS[];
+ // Current metering areas. Camera driver uses these areas to decide
+ // exposure.
+ //
+ // Before accessing this parameter, apps should check
+ // KEY_MAX_NUM_METERING_AREAS first to know the maximum number of metering
+ // areas first. If the value is 0, metering area is not supported.
+ //
+ // Each metering area is a rectangle with specified weight. The direction is
+ // relative to the sensor orientation, that is, what the sensor sees. The
+ // direction is not affected by the rotation or mirroring of
+ // CAMERA_CMD_SET_DISPLAY_ORIENTATION. Coordinates of the rectangle range
+ // from -1000 to 1000. (-1000, -1000) is the upper left point. (1000, 1000)
+ // is the lower right point. The length and width of metering areas cannot
+ // be 0 or negative.
+ //
+ // The fifth element is the weight. Values for weight must range from 1 to
+ // 1000. The weight should be interpreted as a per-pixel weight - all
+ // pixels in the area have the specified weight. This means a small area
+ // with the same weight as a larger area will have less influence on the
+ // metering than the larger area. Metering areas can partially overlap and
+ // the driver will add the weights in the overlap region.
+ //
+ // A special case of all-zero single metering area means driver to decide
+ // the metering area. For example, the driver may use more signals to decide
+ // metering areas and change them dynamically. Apps can set all-zero if they
+ // want the driver to decide metering areas.
+ //
+ // Metering areas are relative to the current field of view (KEY_ZOOM).
+ // No matter what the zoom level is, (-1000,-1000) represents the top of the
+ // currently visible camera frame. The metering area cannot be set to be
+ // outside the current field of view, even when using zoom.
+ //
+ // No matter what metering areas are, the final exposure are compensated
+ // by KEY_EXPOSURE_COMPENSATION.
+ // Example value: "(-10,-10,0,0,300),(0,0,10,10,700)". Read/write.
+ static const char KEY_METERING_AREAS[];
// Current zoom value.
// Example value: "0" or "6". Read/write.
static const char KEY_ZOOM[];
@@ -349,6 +447,7 @@ public:
// Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
static const char TRUE[];
+ static const char FALSE[];
// Value for KEY_FOCUS_DISTANCES.
static const char FOCUS_DISTANCE_INFINITY[];
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index 2344b3f..400d7f4 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -102,12 +102,6 @@ public:
// send command to camera driver
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
- // return the total number of available video buffers
- virtual int32_t getNumberOfVideoBuffers() const = 0;
-
- // return the individual video buffer corresponding to the given index.
- virtual sp<IMemory> getVideoBuffer(int32_t index) const = 0;
-
// tell the camera hal to store meta data or real YUV data in video buffers.
virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
};
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
index add33d3..dfca228 100644
--- a/include/drm/DrmInfoEvent.h
+++ b/include/drm/DrmInfoEvent.h
@@ -77,7 +77,7 @@ public:
* @param[in] infoType Type of information
* @param[in] message Message description
*/
- DrmInfoEvent(int uniqueId, int infoType, const String8& message);
+ DrmInfoEvent(int uniqueId, int infoType, const String8 message);
/**
* Destructor for DrmInfoEvent
@@ -104,12 +104,12 @@ public:
*
* @return Message description
*/
- const String8& getMessage() const;
+ const String8 getMessage() const;
private:
int mUniqueId;
int mInfoType;
- const String8& mMessage;
+ const String8 mMessage;
};
};
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index 7a0bf4f..b8fe46d 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -69,7 +69,7 @@ public:
* @return
* Handle for the decryption session
*/
- DecryptHandle* openDecryptSession(int fd, off64_t offset, off64_t length);
+ sp<DecryptHandle> openDecryptSession(int fd, off64_t offset, off64_t length);
/**
* Open the decrypt session to decrypt the given protected content
@@ -78,7 +78,7 @@ public:
* @return
* Handle for the decryption session
*/
- DecryptHandle* openDecryptSession(const char* uri);
+ sp<DecryptHandle> openDecryptSession(const char* uri);
/**
* Close the decrypt session for the given handle
@@ -87,7 +87,7 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t closeDecryptSession(DecryptHandle* decryptHandle);
+ status_t closeDecryptSession(sp<DecryptHandle> &decryptHandle);
/**
* Consumes the rights for a content.
@@ -101,7 +101,7 @@ public:
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure.
* In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned.
*/
- status_t consumeRights(DecryptHandle* decryptHandle, int action, bool reserve);
+ status_t consumeRights(sp<DecryptHandle> &decryptHandle, int action, bool reserve);
/**
* Informs the DRM engine about the playback actions performed on the DRM files.
@@ -113,7 +113,8 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+ status_t setPlaybackStatus(
+ sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
/**
* Initialize decryption for the given unit of the protected content
@@ -125,7 +126,7 @@ public:
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
status_t initializeDecryptUnit(
- DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
/**
* Decrypt the protected content buffers for the given unit
@@ -144,7 +145,7 @@ public:
* DRM_ERROR_DECRYPT for failure.
*/
status_t decrypt(
- DecryptHandle* decryptHandle, int decryptUnitId,
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL);
/**
@@ -155,7 +156,8 @@ public:
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
*/
- status_t finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId);
+ status_t finalizeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId);
/**
* Reads the specified number of bytes from an open DRM file.
@@ -167,7 +169,8 @@ public:
*
* @return Number of bytes read. Returns -1 for Failure.
*/
- ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset);
+ ssize_t pread(sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
/**
* Validates whether an action on the DRM content is allowed or not.
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index 454fc99..3330ebc 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -19,6 +19,7 @@
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Errors.h>
@@ -30,14 +31,17 @@ namespace android {
* Error code for DRM Frameowrk
*/
enum {
- DRM_ERROR_BASE = -2000,
-
- DRM_ERROR_UNKNOWN = DRM_ERROR_BASE,
- DRM_ERROR_LICENSE_EXPIRED = DRM_ERROR_BASE - 1,
- DRM_ERROR_SESSION_NOT_OPENED = DRM_ERROR_BASE - 2,
- DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 3,
- DRM_ERROR_DECRYPT = DRM_ERROR_BASE - 4,
- DRM_ERROR_CANNOT_HANDLE = DRM_ERROR_BASE - 5,
+ // The following constant values should be in sync with
+ // media/stagefright/MediaErrors.h
+ ERROR_BASE = -2000,
+
+ DRM_ERROR_UNKNOWN = ERROR_BASE,
+ DRM_ERROR_NO_LICENSE = ERROR_BASE - 1,
+ DRM_ERROR_LICENSE_EXPIRED = ERROR_BASE - 2,
+ DRM_ERROR_SESSION_NOT_OPENED = ERROR_BASE - 3,
+ DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = ERROR_BASE - 4,
+ DRM_ERROR_DECRYPT = ERROR_BASE - 5,
+ DRM_ERROR_CANNOT_HANDLE = ERROR_BASE - 6,
DRM_NO_ERROR = NO_ERROR
};
@@ -251,7 +255,7 @@ public:
/**
* Defines decryption handle
*/
-class DecryptHandle {
+class DecryptHandle : public RefBase {
public:
/**
* Decryption session Handle
@@ -307,8 +311,13 @@ public:
decryptId(INVALID_VALUE),
mimeType(""),
decryptApiType(INVALID_VALUE),
- status(INVALID_VALUE) {
+ status(INVALID_VALUE),
+ decryptInfo(NULL) {
+
+ }
+ ~DecryptHandle() {
+ delete decryptInfo; decryptInfo = NULL;
}
bool operator<(const DecryptHandle& handle) const {
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
new file mode 100644
index 0000000..79d5d82
--- /dev/null
+++ b/include/media/AudioParameter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008-2011 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 ANDROID_AUDIOPARAMETER_H_
+#define ANDROID_AUDIOPARAMETER_H_
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class AudioParameter {
+
+public:
+ AudioParameter() {}
+ AudioParameter(const String8& keyValuePairs);
+ virtual ~AudioParameter();
+
+ // reserved parameter keys for changing standard parameters with setParameters() function.
+ // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
+ // configuration changes and act accordingly.
+ // keyRouting: to change audio routing, value is an int in audio_devices_t
+ // keySamplingRate: to change sampling rate routing, value is an int
+ // keyFormat: to change audio format, value is an int in audio_format_t
+ // keyChannels: to change audio channel configuration, value is an int in audio_channels_t
+ // keyFrameCount: to change audio output frame count, value is an int
+ // keyInputSource: to change audio input source, value is an int in audio_source_t
+ // (defined in media/mediarecorder.h)
+ static const char *keyRouting;
+ static const char *keySamplingRate;
+ static const char *keyFormat;
+ static const char *keyChannels;
+ static const char *keyFrameCount;
+ static const char *keyInputSource;
+
+ String8 toString();
+
+ status_t add(const String8& key, const String8& value);
+ status_t addInt(const String8& key, const int value);
+ status_t addFloat(const String8& key, const float value);
+
+ status_t remove(const String8& key);
+
+ status_t get(const String8& key, String8& value);
+ status_t getInt(const String8& key, int& value);
+ status_t getFloat(const String8& key, float& value);
+ status_t getAt(size_t index, String8& key, String8& value);
+
+ size_t size() { return mParameters.size(); }
+
+private:
+ String8 mKeyValuePairs;
+ KeyedVector <String8, String8> mParameters;
+};
+
+}; // namespace android
+
+#endif /*ANDROID_AUDIOPARAMETER_H_*/
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 293764d..def3612 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -30,6 +30,7 @@
#include <binder/IMemory.h>
#include <utils/threads.h>
+#include <hardware/audio.h>
namespace android {
@@ -127,9 +128,9 @@ public:
*
* inputSource: Select the audio input to record to (e.g. AUDIO_SOURCE_DEFAULT).
* sampleRate: Track sampling rate in Hz.
- * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
+ * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
* 16 bits per sample).
- * channels: Channel mask: see AudioSystem::audio_channels.
+ * channels: Channel mask: see audio_channels_t.
* frameCount: Total size of track PCM buffer in frames. This defines the
* latency of the track.
* flags: A bitmask of acoustic values from enum record_flags. It enables
@@ -142,15 +143,15 @@ public:
*/
enum record_flags {
- RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE,
- RECORD_NS_ENABLE = AudioSystem::NS_ENABLE,
- RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE
+ RECORD_AGC_ENABLE = AUDIO_IN_ACOUSTICS_AGC_ENABLE,
+ RECORD_NS_ENABLE = AUDIO_IN_ACOUSTICS_NS_ENABLE,
+ RECORD_IIR_ENABLE = AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE,
};
AudioRecord(int inputSource,
uint32_t sampleRate = 0,
int format = 0,
- uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
@@ -176,7 +177,7 @@ public:
status_t set(int inputSource = 0,
uint32_t sampleRate = 0,
int format = 0,
- uint32_t channels = AudioSystem::CHANNEL_IN_MONO,
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO,
int frameCount = 0,
uint32_t flags = 0,
callback_t cbf = 0,
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 2dc4beb..eb61a87 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -21,10 +21,15 @@
#include <utils/threads.h>
#include <media/IAudioFlinger.h>
+#include <hardware/audio.h>
+#include <hardware/audio_policy.h>
+
+/* XXX: Should be include by all the users instead */
+#include <media/AudioParameter.h>
+
namespace android {
typedef void (*audio_error_callback)(status_t err);
-typedef int audio_io_handle_t;
class IAudioPolicyService;
class String8;
@@ -33,151 +38,6 @@ class AudioSystem
{
public:
- enum stream_type {
- DEFAULT =-1,
- VOICE_CALL = 0,
- SYSTEM = 1,
- RING = 2,
- MUSIC = 3,
- ALARM = 4,
- NOTIFICATION = 5,
- BLUETOOTH_SCO = 6,
- ENFORCED_AUDIBLE = 7, // Sounds that cannot be muted by user and must be routed to speaker
- DTMF = 8,
- TTS = 9,
- NUM_STREAM_TYPES
- };
-
- // Audio sub formats (see AudioSystem::audio_format).
- enum pcm_sub_format {
- PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility
- PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility
- };
-
- // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify
- // bit rate, stereo mode, version...
- enum mp3_sub_format {
- //TODO
- };
-
- // AMR NB/WB sub format field definition: specify frame block interleaving, bandwidth efficient or octet aligned,
- // encoding mode for recording...
- enum amr_sub_format {
- //TODO
- };
-
- // AAC sub format field definition: specify profile or bitrate for recording...
- enum aac_sub_format {
- //TODO
- };
-
- // VORBIS sub format field definition: specify quality for recording...
- enum vorbis_sub_format {
- //TODO
- };
-
- // Audio format consists in a main format field (upper 8 bits) and a sub format field (lower 24 bits).
- // The main format indicates the main codec type. The sub format field indicates options and parameters
- // for each format. The sub format is mainly used for record to indicate for instance the requested bitrate
- // or profile. It can also be used for certain formats to give informations not present in the encoded
- // audio stream (e.g. octet alignement for AMR).
- enum audio_format {
- INVALID_FORMAT = -1,
- FORMAT_DEFAULT = 0,
- PCM = 0x00000000, // must be 0 for backward compatibility
- MP3 = 0x01000000,
- AMR_NB = 0x02000000,
- AMR_WB = 0x03000000,
- AAC = 0x04000000,
- HE_AAC_V1 = 0x05000000,
- HE_AAC_V2 = 0x06000000,
- VORBIS = 0x07000000,
- MAIN_FORMAT_MASK = 0xFF000000,
- SUB_FORMAT_MASK = 0x00FFFFFF,
- // Aliases
- PCM_16_BIT = (PCM|PCM_SUB_16_BIT),
- PCM_8_BIT = (PCM|PCM_SUB_8_BIT)
- };
-
-
- // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java
- enum audio_channels {
- // output channels
- CHANNEL_OUT_FRONT_LEFT = 0x4,
- CHANNEL_OUT_FRONT_RIGHT = 0x8,
- CHANNEL_OUT_FRONT_CENTER = 0x10,
- CHANNEL_OUT_LOW_FREQUENCY = 0x20,
- CHANNEL_OUT_BACK_LEFT = 0x40,
- CHANNEL_OUT_BACK_RIGHT = 0x80,
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100,
- CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200,
- CHANNEL_OUT_BACK_CENTER = 0x400,
- CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT,
- CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT),
- CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER),
- CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT),
- CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
- CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
- CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
- CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER),
-
- // input channels
- CHANNEL_IN_LEFT = 0x4,
- CHANNEL_IN_RIGHT = 0x8,
- CHANNEL_IN_FRONT = 0x10,
- CHANNEL_IN_BACK = 0x20,
- CHANNEL_IN_LEFT_PROCESSED = 0x40,
- CHANNEL_IN_RIGHT_PROCESSED = 0x80,
- CHANNEL_IN_FRONT_PROCESSED = 0x100,
- CHANNEL_IN_BACK_PROCESSED = 0x200,
- CHANNEL_IN_PRESSURE = 0x400,
- CHANNEL_IN_X_AXIS = 0x800,
- CHANNEL_IN_Y_AXIS = 0x1000,
- CHANNEL_IN_Z_AXIS = 0x2000,
- CHANNEL_IN_VOICE_UPLINK = 0x4000,
- CHANNEL_IN_VOICE_DNLINK = 0x8000,
- CHANNEL_IN_MONO = CHANNEL_IN_FRONT,
- CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT),
- CHANNEL_IN_ALL = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK|
- CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED | CHANNEL_IN_FRONT_PROCESSED | CHANNEL_IN_BACK_PROCESSED|
- CHANNEL_IN_PRESSURE | CHANNEL_IN_X_AXIS | CHANNEL_IN_Y_AXIS | CHANNEL_IN_Z_AXIS |
- CHANNEL_IN_VOICE_UPLINK | CHANNEL_IN_VOICE_DNLINK)
- };
-
- enum audio_mode {
- MODE_INVALID = -2,
- MODE_CURRENT = -1,
- MODE_NORMAL = 0,
- MODE_RINGTONE,
- MODE_IN_CALL,
- MODE_IN_COMMUNICATION,
- NUM_MODES // not a valid entry, denotes end-of-list
- };
-
- enum audio_in_acoustics {
- AGC_ENABLE = 0x0001,
- AGC_DISABLE = 0,
- NS_ENABLE = 0x0002,
- NS_DISABLE = 0,
- TX_IIR_ENABLE = 0x0004,
- TX_DISABLE = 0
- };
-
- // special audio session values
- enum audio_sessions {
- SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream
- // (value must be less than 0)
- SESSION_OUTPUT_MIX = 0, // session for effects applied to output mix. These effects can
- // be moved by audio policy manager to another output stream
- // (value must be 0)
- };
-
/* These are static methods to control the system-wide AudioFlinger
* only privileged processes can have access to them
*/
@@ -189,6 +49,7 @@ public:
// set/get master volume
static status_t setMasterVolume(float value);
static status_t getMasterVolume(float* volume);
+
// mute/unmute audio outputs
static status_t setMasterMute(bool mute);
static status_t getMasterMute(bool* mute);
@@ -201,7 +62,7 @@ public:
static status_t setStreamMute(int stream, bool mute);
static status_t getStreamMute(int stream, bool* mute);
- // set audio mode in audio hardware (see AudioSystem::audio_mode)
+ // set audio mode in audio hardware (see audio_mode_t)
static status_t setMode(int mode);
// returns true in *state if tracks are active on the specified stream or has been active
@@ -222,9 +83,9 @@ public:
static float linearToLog(int volume);
static int logToLinear(float volume);
- static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT);
- static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT);
- static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
+ static status_t getOutputSamplingRate(int* samplingRate, int stream = AUDIO_STREAM_DEFAULT);
+ static status_t getOutputFrameCount(int* frameCount, int stream = AUDIO_STREAM_DEFAULT);
+ static status_t getOutputLatency(uint32_t* latency, int stream = AUDIO_STREAM_DEFAULT);
static bool routedToA2dpOutput(int streamType);
@@ -234,7 +95,7 @@ public:
static status_t setVoiceVolume(float volume);
// return the number of audio frames written by AudioFlinger to audio HAL and
- // audio dsp to DAC since the output on which the specificed stream is playing
+ // audio dsp to DAC since the output on which the specified stream is playing
// has exited standby.
// returned status (from utils/Errors.h) can be:
// - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
@@ -242,93 +103,11 @@ public:
// - BAD_VALUE: invalid parameter
// NOTE: this feature is not supported on all hardware platforms and it is
// necessary to check returned status before using the returned values.
- static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
+ static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = AUDIO_STREAM_DEFAULT);
static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
static int newAudioSessionId();
- //
- // AudioPolicyService interface
- //
-
- enum audio_devices {
- // output devices
- DEVICE_OUT_EARPIECE = 0x1,
- DEVICE_OUT_SPEAKER = 0x2,
- DEVICE_OUT_WIRED_HEADSET = 0x4,
- DEVICE_OUT_WIRED_HEADPHONE = 0x8,
- DEVICE_OUT_BLUETOOTH_SCO = 0x10,
- DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
- DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
- DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
- DEVICE_OUT_AUX_DIGITAL = 0x400,
- DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800,
- DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000,
- DEVICE_OUT_DEFAULT = 0x8000,
- DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
- DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL |
- DEVICE_OUT_ANLG_DOCK_HEADSET | DEVICE_OUT_DGTL_DOCK_HEADSET |
- DEVICE_OUT_DEFAULT),
- DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-
- // input devices
- DEVICE_IN_COMMUNICATION = 0x10000,
- DEVICE_IN_AMBIENT = 0x20000,
- DEVICE_IN_BUILTIN_MIC = 0x40000,
- DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
- DEVICE_IN_WIRED_HEADSET = 0x100000,
- DEVICE_IN_AUX_DIGITAL = 0x200000,
- DEVICE_IN_VOICE_CALL = 0x400000,
- DEVICE_IN_BACK_MIC = 0x800000,
- DEVICE_IN_DEFAULT = 0x80000000,
-
- DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
- DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
- DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT)
- };
-
- // device connection states used for setDeviceConnectionState()
- enum device_connection_state {
- DEVICE_STATE_UNAVAILABLE,
- DEVICE_STATE_AVAILABLE,
- NUM_DEVICE_STATES
- };
-
- // request to open a direct output with getOutput() (by opposition to sharing an output with other AudioTracks)
- enum output_flags {
- OUTPUT_FLAG_INDIRECT = 0x0,
- OUTPUT_FLAG_DIRECT = 0x1
- };
-
- // device categories used for setForceUse()
- enum forced_config {
- FORCE_NONE,
- FORCE_SPEAKER,
- FORCE_HEADPHONES,
- FORCE_BT_SCO,
- FORCE_BT_A2DP,
- FORCE_WIRED_ACCESSORY,
- FORCE_BT_CAR_DOCK,
- FORCE_BT_DESK_DOCK,
- FORCE_ANALOG_DOCK,
- FORCE_DIGITAL_DOCK,
- NUM_FORCE_CONFIG,
- FORCE_DEFAULT = FORCE_NONE
- };
-
- // usages used for setForceUse()
- enum force_use {
- FOR_COMMUNICATION,
- FOR_MEDIA,
- FOR_RECORD,
- FOR_DOCK,
- NUM_FORCE_USE
- };
// types of io configuration change events received with ioConfigChanged()
enum io_config_event {
@@ -359,40 +138,40 @@ public:
//
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
- static status_t setDeviceConnectionState(audio_devices device, device_connection_state state, const char *device_address);
- static device_connection_state getDeviceConnectionState(audio_devices device, const char *device_address);
+ static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
+ static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
static status_t setPhoneState(int state);
static status_t setRingerMode(uint32_t mode, uint32_t mask);
- static status_t setForceUse(force_use usage, forced_config config);
- static forced_config getForceUse(force_use usage);
- static audio_io_handle_t getOutput(stream_type stream,
+ static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
+ static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+ static audio_io_handle_t getOutput(audio_stream_type_t stream,
uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_OUT_STEREO,
- output_flags flags = OUTPUT_FLAG_INDIRECT);
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = AUDIO_CHANNEL_OUT_STEREO,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_INDIRECT);
static status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0);
static status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0);
static void releaseOutput(audio_io_handle_t output);
static audio_io_handle_t getInput(int inputSource,
uint32_t samplingRate = 0,
- uint32_t format = FORMAT_DEFAULT,
- uint32_t channels = CHANNEL_IN_MONO,
- audio_in_acoustics acoustics = (audio_in_acoustics)0);
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO,
+ audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0);
static status_t startInput(audio_io_handle_t input);
static status_t stopInput(audio_io_handle_t input);
static void releaseInput(audio_io_handle_t input);
- static status_t initStreamVolume(stream_type stream,
+ static status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);
- static status_t setStreamVolumeIndex(stream_type stream, int index);
- static status_t getStreamVolumeIndex(stream_type stream, int *index);
+ static status_t setStreamVolumeIndex(audio_stream_type_t stream, int index);
+ static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
- static uint32_t getStrategyForStream(stream_type stream);
- static uint32_t getDevicesForStream(stream_type stream);
+ static uint32_t getStrategyForStream(audio_stream_type_t stream);
+ static uint32_t getDevicesForStream(audio_stream_type_t stream);
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
static status_t registerEffect(effect_descriptor_t *desc,
@@ -406,17 +185,6 @@ public:
// ----------------------------------------------------------------------------
- static uint32_t popCount(uint32_t u);
- static bool isOutputDevice(audio_devices device);
- static bool isInputDevice(audio_devices device);
- static bool isA2dpDevice(audio_devices device);
- static bool isBluetoothScoDevice(audio_devices device);
- static bool isLowVisibility(stream_type stream);
- static bool isOutputChannel(uint32_t channel);
- static bool isInputChannel(uint32_t channel);
- static bool isValidFormat(uint32_t format);
- static bool isLinearPCM(uint32_t format);
-
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
@@ -468,50 +236,6 @@ private:
static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
};
-class AudioParameter {
-
-public:
- AudioParameter() {}
- AudioParameter(const String8& keyValuePairs);
- virtual ~AudioParameter();
-
- // reserved parameter keys for changing standard parameters with setParameters() function.
- // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
- // configuration changes and act accordingly.
- // keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
- // keySamplingRate: to change sampling rate routing, value is an int
- // keyFormat: to change audio format, value is an int in AudioSystem::audio_format
- // keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
- // keyFrameCount: to change audio output frame count, value is an int
- // keyInputSource: to change audio input source, value is an int in audio_source
- // (defined in media/mediarecorder.h)
- static const char *keyRouting;
- static const char *keySamplingRate;
- static const char *keyFormat;
- static const char *keyChannels;
- static const char *keyFrameCount;
- static const char *keyInputSource;
-
- String8 toString();
-
- status_t add(const String8& key, const String8& value);
- status_t addInt(const String8& key, const int value);
- status_t addFloat(const String8& key, const float value);
-
- status_t remove(const String8& key);
-
- status_t get(const String8& key, String8& value);
- status_t getInt(const String8& key, int& value);
- status_t getFloat(const String8& key, float& value);
- status_t getAt(size_t index, String8& key, String8& value);
-
- size_t size() { return mParameters.size(); }
-
-private:
- String8 mKeyValuePairs;
- KeyedVector <String8, String8> mParameters;
-};
-
}; // namespace android
#endif /*ANDROID_AUDIOSYSTEM_H_*/
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 3e346db..de928da 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -30,7 +30,6 @@
#include <binder/IMemory.h>
#include <utils/threads.h>
-
namespace android {
// ----------------------------------------------------------------------------
@@ -126,11 +125,11 @@ public:
* Parameters:
*
* streamType: Select the type of audio stream this track is attached to
- * (e.g. AudioSystem::MUSIC).
+ * (e.g. AUDIO_STREAM_MUSIC).
* sampleRate: Track sampling rate in Hz.
- * format: Audio format (e.g AudioSystem::PCM_16_BIT for signed
+ * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
* 16 bits per sample).
- * channels: Channel mask: see AudioSystem::audio_channels.
+ * channels: Channel mask: see audio_channels_t.
* frameCount: Total size of track PCM buffer in frames. This defines the
* latency of the track.
* flags: Reserved for future use.
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
index b97c22e..a5ad846 100644
--- a/include/media/EffectApi.h
+++ b/include/media/EffectApi.h
@@ -602,9 +602,9 @@ enum audio_device_e {
// Audio mode
enum audio_mode_e {
- AUDIO_MODE_NORMAL, // device idle
- AUDIO_MODE_RINGTONE, // device ringing
- AUDIO_MODE_IN_CALL // audio call connected (VoIP or telephony)
+ AUDIO_EFFECT_MODE_NORMAL, // device idle
+ AUDIO_EFFECT_MODE_RINGTONE, // device ringing
+ AUDIO_EFFECT_MODE_IN_CALL, // audio call connected (VoIP or telephony)
};
// Values for "accessMode" field of buffer_config_t:
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 720a562..09b2bfe 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -26,6 +26,7 @@
#include <binder/IInterface.h>
#include <media/AudioSystem.h>
+#include <hardware/audio_policy.h>
namespace android {
@@ -39,42 +40,42 @@ public:
//
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
- virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
const char *device_address) = 0;
- virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+ virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
const char *device_address) = 0;
virtual status_t setPhoneState(int state) = 0;
virtual status_t setRingerMode(uint32_t mode, uint32_t mask) = 0;
- virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) = 0;
- virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage) = 0;
- virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) = 0;
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
+ virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = 0,
- AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT) = 0;
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_INDIRECT) = 0;
virtual status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0) = 0;
virtual status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0) = 0;
virtual void releaseOutput(audio_io_handle_t output) = 0;
virtual audio_io_handle_t getInput(int inputSource,
uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = 0,
- AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0) = 0;
+ audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0) = 0;
virtual status_t startInput(audio_io_handle_t input) = 0;
virtual status_t stopInput(audio_io_handle_t input) = 0;
virtual void releaseInput(audio_io_handle_t input) = 0;
- virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax) = 0;
- virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0;
- virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0;
- virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0;
- virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream) = 0;
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, int index) = 0;
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index) = 0;
+ virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
+ virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0;
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
virtual status_t registerEffect(effect_descriptor_t *desc,
audio_io_handle_t output,
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
index 8e3cdbb..1c1c268 100644
--- a/include/media/IMediaMetadataRetriever.h
+++ b/include/media/IMediaMetadataRetriever.h
@@ -18,10 +18,11 @@
#ifndef ANDROID_IMEDIAMETADATARETRIEVER_H
#define ANDROID_IMEDIAMETADATARETRIEVER_H
-#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IMemory.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
namespace android {
@@ -30,7 +31,11 @@ class IMediaMetadataRetriever: public IInterface
public:
DECLARE_META_INTERFACE(MediaMetadataRetriever);
virtual void disconnect() = 0;
- virtual status_t setDataSource(const char* srcUrl) = 0;
+
+ virtual status_t setDataSource(
+ const char *srcUrl,
+ const KeyedVector<String8, String8> *headers = NULL) = 0;
+
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0;
virtual sp<IMemory> extractAlbumArt() = 0;
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 70519ef..d552b2e 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -24,7 +24,6 @@
namespace android {
class Parcel;
-class ISurface;
class Surface;
class ISurfaceTexture;
@@ -52,6 +51,8 @@ public:
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t setAuxEffectSendLevel(float level) = 0;
virtual status_t attachAuxEffect(int effectId) = 0;
+ virtual status_t setParameter(int key, const Parcel& request) = 0;
+ virtual status_t getParameter(int key, Parcel* reply) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
index eee6c97..daec1c7 100644
--- a/include/media/IMediaPlayerClient.h
+++ b/include/media/IMediaPlayerClient.h
@@ -28,7 +28,7 @@ class IMediaPlayerClient: public IInterface
public:
DECLARE_META_INTERFACE(MediaPlayerClient);
- virtual void notify(int msg, int ext1, int ext2) = 0;
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 16a9342..3c65147 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -33,7 +33,6 @@ namespace android {
class IMemory;
class IOMXObserver;
class IOMXRenderer;
-class ISurface;
class Surface;
class IOMX : public IInterface {
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
index 0449122..27b7e4d 100644
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -30,7 +30,11 @@ class MediaMetadataRetrieverBase : public RefBase
public:
MediaMetadataRetrieverBase() {}
virtual ~MediaMetadataRetrieverBase() {}
- virtual status_t setDataSource(const char *url) = 0;
+
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers = NULL) = 0;
+
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
virtual MediaAlbumArt* extractAlbumArt() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 117d7eb..f0401cc 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -32,7 +32,6 @@
namespace android {
class Parcel;
-class ISurface;
class Surface;
class ISurfaceTexture;
@@ -56,7 +55,8 @@ enum player_type {
// callback mechanism for passing messages to MediaPlayer object
-typedef void (*notify_callback_f)(void* cookie, int msg, int ext1, int ext2);
+typedef void (*notify_callback_f)(void* cookie,
+ int msg, int ext1, int ext2, const Parcel *obj);
// abstract base class - use MediaPlayerInterface
class MediaPlayerBase : public RefBase
@@ -85,7 +85,7 @@ public:
// audio data.
virtual status_t open(
uint32_t sampleRate, int channelCount,
- int format=AudioSystem::PCM_16_BIT,
+ int format=AUDIO_FORMAT_PCM_16_BIT,
int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
AudioCallback cb = NULL,
void *cookie = NULL) = 0;
@@ -132,6 +132,8 @@ public:
virtual status_t reset() = 0;
virtual status_t setLooping(int loop) = 0;
virtual player_type playerType() = 0;
+ virtual status_t setParameter(int key, const Parcel &request) = 0;
+ virtual status_t getParameter(int key, Parcel *reply) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
@@ -160,9 +162,10 @@ public:
mCookie = cookie; mNotify = notifyFunc;
}
- void sendEvent(int msg, int ext1=0, int ext2=0) {
+ void sendEvent(int msg, int ext1=0, int ext2=0,
+ const Parcel *obj=NULL) {
Mutex::Autolock autoLock(mNotifyLock);
- if (mNotify) mNotify(mCookie, msg, ext1, ext2);
+ if (mNotify) mNotify(mCookie, msg, ext1, ext2, obj);
}
private:
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index c42346e..5fe7722 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -20,6 +20,8 @@
#include <media/mediarecorder.h>
+#include <hardware/audio.h>
+
namespace android {
class Surface;
@@ -29,7 +31,7 @@ struct MediaRecorderBase {
virtual ~MediaRecorderBase() {}
virtual status_t init() = 0;
- virtual status_t setAudioSource(audio_source as) = 0;
+ virtual status_t setAudioSource(audio_source_t as) = 0;
virtual status_t setVideoSource(video_source vs) = 0;
virtual status_t setOutputFormat(output_format of) = 0;
virtual status_t setAudioEncoder(audio_encoder ae) = 0;
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
new file mode 100644
index 0000000..290b748
--- /dev/null
+++ b/include/media/MemoryLeakTrackUtil.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2011, 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 MEMORY_LEAK_TRACK_UTIL_H
+#define MEMORY_LEAK_TRACK_UTIL_H
+
+namespace android {
+/*
+ * Dump the memory adddress of the calling process to the given fd.
+ */
+extern void dumpMemoryAddresses(int fd);
+
+};
+
+#endif // MEMORY_LEAK_TRACK_UTIL_H
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index e905006..28f305d 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -47,6 +47,13 @@ enum {
METADATA_KEY_ALBUMARTIST = 13,
METADATA_KEY_DISC_NUMBER = 14,
METADATA_KEY_COMPILATION = 15,
+ METADATA_KEY_HAS_AUDIO = 16,
+ METADATA_KEY_HAS_VIDEO = 17,
+ METADATA_KEY_VIDEO_WIDTH = 18,
+ METADATA_KEY_VIDEO_HEIGHT = 19,
+ METADATA_KEY_BITRATE = 20,
+ METADATA_KEY_TIMED_TEXT_LANGUAGES = 21,
+
// Add more here...
};
@@ -56,7 +63,11 @@ public:
MediaMetadataRetriever();
~MediaMetadataRetriever();
void disconnect();
- status_t setDataSource(const char* dataSourceUrl);
+
+ status_t setDataSource(
+ const char *dataSourceUrl,
+ const KeyedVector<String8, String8> *headers = NULL);
+
status_t setDataSource(int fd, int64_t offset, int64_t length);
sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
sp<IMemory> extractAlbumArt();
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 528eeb9..cfa4cfd 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -37,6 +37,7 @@ enum media_event_type {
MEDIA_BUFFERING_UPDATE = 3,
MEDIA_SEEK_COMPLETE = 4,
MEDIA_SET_VIDEO_SIZE = 5,
+ MEDIA_TIMED_TEXT = 99,
MEDIA_ERROR = 100,
MEDIA_INFO = 200,
};
@@ -124,12 +125,15 @@ enum media_player_states {
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
};
+enum media_set_parameter_keys {
+ KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
+};
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
class MediaPlayerListener: virtual public RefBase
{
public:
- virtual void notify(int msg, int ext1, int ext2) = 0;
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0;
};
class MediaPlayer : public BnMediaPlayerClient,
@@ -166,7 +170,7 @@ public:
status_t setLooping(int loop);
bool isLooping();
status_t setVolume(float leftVolume, float rightVolume);
- void notify(int msg, int ext1, int ext2);
+ void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
static sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
static sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
status_t invoke(const Parcel& request, Parcel *reply);
@@ -176,6 +180,9 @@ public:
int getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
status_t attachAuxEffect(int effectId);
+ status_t setParameter(int key, const Parcel& request);
+ status_t getParameter(int key, Parcel* reply);
+
private:
void clear_l();
status_t seekTo_l(int msec);
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a710546..18a3c6a 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -33,23 +33,6 @@ class ICamera;
typedef void (*media_completion_f)(status_t status, void *cookie);
-/* Do not change these values without updating their counterparts
- * in media/java/android/media/MediaRecorder.java!
- */
-enum audio_source {
- AUDIO_SOURCE_DEFAULT = 0,
- AUDIO_SOURCE_MIC = 1,
- AUDIO_SOURCE_VOICE_UPLINK = 2,
- AUDIO_SOURCE_VOICE_DOWNLINK = 3,
- AUDIO_SOURCE_VOICE_CALL = 4,
- AUDIO_SOURCE_CAMCORDER = 5,
- AUDIO_SOURCE_VOICE_RECOGNITION = 6,
- AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
- AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_COMMUNICATION,
-
- AUDIO_SOURCE_LIST_END // must be last - used to validate audio source type
-};
-
enum video_source {
VIDEO_SOURCE_DEFAULT = 0,
VIDEO_SOURCE_CAMERA = 1,
@@ -104,35 +87,62 @@ enum video_encoder {
};
/*
- * The state machine of the media_recorder uses a set of different state names.
- * The mapping between the media_recorder and the pvauthorengine is shown below:
- *
- * mediarecorder pvauthorengine
- * ----------------------------------------------------------------
- * MEDIA_RECORDER_ERROR ERROR
- * MEDIA_RECORDER_IDLE IDLE
- * MEDIA_RECORDER_INITIALIZED OPENED
- * MEDIA_RECORDER_DATASOURCE_CONFIGURED
- * MEDIA_RECORDER_PREPARED INITIALIZED
- * MEDIA_RECORDER_RECORDING RECORDING
+ * The state machine of the media_recorder.
*/
enum media_recorder_states {
+ // Error state.
MEDIA_RECORDER_ERROR = 0,
+
+ // Recorder was just created.
MEDIA_RECORDER_IDLE = 1 << 0,
+
+ // Recorder has been initialized.
MEDIA_RECORDER_INITIALIZED = 1 << 1,
+
+ // Configuration of the recorder has been completed.
MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2,
+
+ // Recorder is ready to start.
MEDIA_RECORDER_PREPARED = 1 << 3,
+
+ // Recording is in progress.
MEDIA_RECORDER_RECORDING = 1 << 4,
};
// The "msg" code passed to the listener in notify.
enum media_recorder_event_type {
+ MEDIA_RECORDER_EVENT_LIST_START = 1,
MEDIA_RECORDER_EVENT_ERROR = 1,
- MEDIA_RECORDER_EVENT_INFO = 2
+ MEDIA_RECORDER_EVENT_INFO = 2,
+ MEDIA_RECORDER_EVENT_LIST_END = 99,
+
+ // Track related event types
+ MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_EVENT_ERROR = 100,
+ MEDIA_RECORDER_TRACK_EVENT_INFO = 101,
+ MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000,
};
+/*
+ * The (part of) "what" code passed to the listener in notify.
+ * When the error or info type is track specific, the what has
+ * the following layout:
+ * the left-most 16-bit is meant for error or info type.
+ * the right-most 4-bit is meant for track id.
+ * the rest is reserved.
+ *
+ * | track id | reserved | error or info type |
+ * 31 28 16 0
+ *
+ */
enum media_recorder_error_type {
- MEDIA_RECORDER_ERROR_UNKNOWN = 1
+ MEDIA_RECORDER_ERROR_UNKNOWN = 1,
+
+ // Track related error type
+ MEDIA_RECORDER_TRACK_ERROR_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_ERROR_GENERAL = 100,
+ MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME = 200,
+ MEDIA_RECORDER_TRACK_ERROR_LIST_END = 1000,
};
// The codes are distributed as follow:
@@ -141,11 +151,15 @@ enum media_recorder_error_type {
//
enum media_recorder_info_type {
MEDIA_RECORDER_INFO_UNKNOWN = 1,
+
MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800,
MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801,
- MEDIA_RECORDER_INFO_COMPLETION_STATUS = 802,
- MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS = 803,
- MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS = 804,
+
+ // All track related informtional events start here
+ MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000,
+ MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000,
+ MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001,
+ MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000,
};
// ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index d12ee9c..0b79324 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -108,6 +108,8 @@ private:
void reset();
+ uint32_t getNumFramesPendingPlayout() const;
+
AudioPlayer(const AudioPlayer &);
AudioPlayer &operator=(const AudioPlayer &);
};
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 9e6f0e2..20a9e16 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -24,16 +24,18 @@
#include <media/stagefright/MediaBuffer.h>
#include <utils/List.h>
+#include <hardware/audio.h>
+
namespace android {
class AudioRecord;
struct AudioSource : public MediaSource, public MediaBufferObserver {
// Note that the "channels" parameter is _not_ the number of channels,
- // but a bitmask of AudioSystem::audio_channels constants.
+ // but a bitmask of audio_channels_t constants.
AudioSource(
int inputSource, uint32_t sampleRate,
- uint32_t channels = AudioSystem::CHANNEL_IN_MONO);
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO);
status_t initCheck() const;
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 4a39fbf..bb25bae 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -99,34 +99,6 @@ public:
virtual sp<MetaData> getFormat();
/**
- * Retrieve the total number of video buffers available from
- * this source.
- *
- * This method is useful if these video buffers are used
- * for passing video frame data to other media components,
- * such as OMX video encoders, in order to eliminate the
- * memcpy of the data.
- *
- * @return the total numbner of video buffers. Returns 0 to
- * indicate that this source does not make the video
- * buffer information availalble.
- */
- size_t getNumberOfVideoBuffers() const;
-
- /**
- * Retrieve the individual video buffer available from
- * this source.
- *
- * @param index the index corresponding to the video buffer.
- * Valid range of the index is [0, n], where n =
- * getNumberOfVideoBuffers() - 1.
- *
- * @return the video buffer corresponding to the given index.
- * If index is out of range, 0 should be returned.
- */
- sp<IMemory> getVideoBuffer(size_t index) const;
-
- /**
* Tell whether this camera source stores meta data or real YUV
* frame data in video buffers.
*
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index f95e56a..6b6fcdf 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -75,15 +75,17 @@ public:
static void RegisterDefaultSniffers();
// for DRM
- virtual DecryptHandle* DrmInitialization() {
+ virtual sp<DecryptHandle> DrmInitialization() {
return NULL;
}
- virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {};
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {};
virtual String8 getUri() {
return String8();
}
+ virtual String8 getMIMEType() const;
+
protected:
virtual ~DataSource() {}
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 51a4343..6cf86dc 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -38,9 +38,9 @@ public:
virtual status_t getSize(off64_t *size);
- virtual DecryptHandle* DrmInitialization();
+ virtual sp<DecryptHandle> DrmInitialization();
- virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
protected:
virtual ~FileSource();
@@ -52,7 +52,7 @@ private:
Mutex mLock;
/*for DRM*/
- DecryptHandle *mDecryptHandle;
+ sp<DecryptHandle> mDecryptHandle;
DrmManagerClient *mDrmManagerClient;
int64_t mDrmBufOffset;
int64_t mDrmBufSize;
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index d1ecaaf..946a0aa 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -84,7 +84,7 @@ struct UseAndroidNativeBufferParams {
OMX_U32 nPortIndex;
OMX_PTR pAppPrivate;
OMX_BUFFERHEADERTYPE **bufferHeader;
- const sp<android_native_buffer_t>& nativeBuffer;
+ const sp<ANativeWindowBuffer>& nativeBuffer;
};
// A pointer to this struct is passed to OMX_GetParameter when the extension
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 5c5229d..15f86ea 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -157,7 +157,7 @@ private:
bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
bool isFileStreamable() const;
- void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
+ void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
void writeCompositionMatrix(int32_t degrees);
MPEG4Writer(const MPEG4Writer &);
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 66dfff6..5e471c1 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -45,9 +45,12 @@ extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_AVI;
extern const char *MEDIA_MIMETYPE_CONTAINER_WVM;
+extern const char *MEDIA_MIMETYPE_TEXT_3GPP;
+
} // namespace android
#endif // MEDIA_DEFS_H_
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index 1a6d548..7cc993c 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -41,7 +41,17 @@ enum {
INFO_FORMAT_CHANGED = MEDIA_ERROR_BASE - 12,
INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13,
- ERROR_NO_LICENSE = MEDIA_ERROR_BASE - 14,
+ // The following constant values should be in sync with
+ // drm/drm_framework_common.h
+ DRM_ERROR_BASE = -2000,
+
+ ERROR_DRM_UNKNOWN = DRM_ERROR_BASE,
+ ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1,
+ ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2,
+ ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3,
+ ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4,
+ ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5,
+ ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6,
// Heartbeat Error Codes
HEARTBEAT_ERROR_BASE = -3000,
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index f7f2235..4044c5d 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -114,6 +114,9 @@ enum {
// An indication that a video buffer has been rendered.
kKeyRendered = 'rend', // bool (int32_t)
+
+ // The language code for this media
+ kKeyMediaLanguage = 'lang', // cstring
};
enum {
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 4610135..1827c3e 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -83,13 +83,12 @@ struct audio_track_cblk_t
uint8_t frameSize;
uint8_t channelCount;
- uint16_t flags;
-
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
- uint16_t waitTimeMs; // Cumulated wait time
+ uint16_t waitTimeMs; // Cumulated wait time
uint16_t sendLevel;
- uint16_t reserved;
+ volatile int32_t flags;
+
// Cache line boundary (32 bytes)
audio_track_cblk_t();
uint32_t stepUser(uint32_t frameCount);
@@ -98,6 +97,7 @@ struct audio_track_cblk_t
uint32_t framesAvailable();
uint32_t framesAvailable_l();
uint32_t framesReady();
+ bool tryLock();
};
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index c7db9a6..6b1fa77 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -26,14 +26,11 @@
#endif
#include <private/pixelflinger/ggl_context.h>
-#include <hardware/copybit.h>
#include <hardware/gralloc.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
-struct android_native_buffer_t;
-
namespace android {
@@ -604,14 +601,6 @@ struct prims_t {
void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
};
-struct copybits_context_t {
- // A handle to the blit engine, if it exists, else NULL.
- copybit_device_t* blitEngine;
- int32_t minScale;
- int32_t maxScale;
- android_native_buffer_t* drawSurfaceBuffer;
-};
-
struct ogles_context_t {
context_t rasterizer;
array_machine_t arrays __attribute__((aligned(32)));
@@ -636,13 +625,6 @@ struct ogles_context_t {
EGLSurfaceManager* surfaceManager;
EGLBufferObjectManager* bufferObjectManager;
- // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is
- // defined, but it is always present because ogles_context_t is a public
- // struct that is used by clients of libagl. We want the size and offsets
- // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined.
-
- copybits_context_t copybits;
-
GLenum error;
static inline ogles_context_t* get() {
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index ff34707..f49267e 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -105,7 +105,7 @@ LOCAL_SRC_FILES:= \
LOCAL_MODULE:= libmusicbundle
-LOCAL_PRELINK_MODULE := false
+
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/Eq/lib \
@@ -168,7 +168,7 @@ LOCAL_SRC_FILES:= \
LOCAL_MODULE:= libreverb
-LOCAL_PRELINK_MODULE := false
+
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/Reverb/lib \
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 2e9b9b4..99cfdfa 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -13,7 +13,7 @@ LOCAL_MODULE:= libbundlewrapper
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
-LOCAL_PRELINK_MODULE := false
+
LOCAL_STATIC_LIBRARIES += libmusicbundle
@@ -47,7 +47,7 @@ LOCAL_MODULE:= libreverbwrapper
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
-LOCAL_PRELINK_MODULE := false
+
LOCAL_STATIC_LIBRARIES += libreverb
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index e6ff654..3a0f438 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -25,6 +25,6 @@ endif
LOCAL_C_INCLUDES := \
$(call include-path-for, graphics corecg)
-LOCAL_PRELINK_MODULE := false
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index fd4c6c6..121e38a 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -1,4 +1,14 @@
LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AudioParameter.cpp
+LOCAL_MODULE:= libmedia_helper
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
@@ -33,13 +43,16 @@ LOCAL_SRC_FILES:= \
IEffectClient.cpp \
AudioEffect.cpp \
Visualizer.cpp \
+ MemoryLeakTrackUtil.cpp \
fixedfft.cpp.arm
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat \
- libsurfaceflinger_client libcamera_client libstagefright_foundation \
+ libcamera_client libstagefright_foundation \
libgui
+LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper
+
LOCAL_MODULE:= libmedia
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index aadeba5..a043329 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -170,7 +170,6 @@ AudioEffect::~AudioEffect()
LOGV("Destructor %p", this);
if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
- setEnabled(false);
if (mIEffect != NULL) {
mIEffect->disconnect();
mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
new file mode 100644
index 0000000..59ccfd0
--- /dev/null
+++ b/media/libmedia/AudioParameter.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2006-2011 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_TAG "AudioParameter"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include <media/AudioParameter.h>
+
+namespace android {
+
+const char *AudioParameter::keyRouting = "routing";
+const char *AudioParameter::keySamplingRate = "sampling_rate";
+const char *AudioParameter::keyFormat = "format";
+const char *AudioParameter::keyChannels = "channels";
+const char *AudioParameter::keyFrameCount = "frame_count";
+const char *AudioParameter::keyInputSource = "input_source";
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+ char *str = new char[keyValuePairs.length()+1];
+ mKeyValuePairs = keyValuePairs;
+
+ strcpy(str, keyValuePairs.string());
+ char *pair = strtok(str, ";");
+ while (pair != NULL) {
+ if (strlen(pair) != 0) {
+ size_t eqIdx = strcspn(pair, "=");
+ String8 key = String8(pair, eqIdx);
+ String8 value;
+ if (eqIdx == strlen(pair)) {
+ value = String8("");
+ } else {
+ value = String8(pair + eqIdx + 1);
+ }
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ } else {
+ mParameters.replaceValueFor(key, value);
+ }
+ } else {
+ LOGV("AudioParameter() cstor empty key value pair");
+ }
+ pair = strtok(NULL, ";");
+ }
+
+ delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+ mParameters.clear();
+}
+
+String8 AudioParameter::toString()
+{
+ String8 str = String8("");
+
+ size_t size = mParameters.size();
+ for (size_t i = 0; i < size; i++) {
+ str += mParameters.keyAt(i);
+ str += "=";
+ str += mParameters.valueAt(i);
+ if (i < (size - 1)) str += ";";
+ }
+ return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ return NO_ERROR;
+ } else {
+ mParameters.replaceValueFor(key, value);
+ return ALREADY_EXISTS;
+ }
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+ char str[12];
+ if (snprintf(str, 12, "%d", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+ char str[23];
+ if (snprintf(str, 23, "%.10f", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ mParameters.removeItem(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ value = mParameters.valueFor(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ int val;
+ if (sscanf(str8.string(), "%d", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ float val;
+ if (sscanf(str8.string(), "%f", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
+
+status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
+{
+ if (mParameters.size() > index) {
+ key = mParameters.keyAt(index);
+ value = mParameters.valueAt(index);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a18bedb..8438714 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -35,6 +35,10 @@
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
+#include <utils/Atomic.h>
+
+#include <hardware/audio.h>
+#include <cutils/bitops.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -65,8 +69,8 @@ status_t AudioRecord::getMinFrameCount(
// We double the size of input buffer for ping pong use of record buffer.
size <<= 1;
- if (AudioSystem::isLinearPCM(format)) {
- size /= channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+ if (audio_is_linear_pcm(format)) {
+ size /= channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? 2 : 1);
}
*frameCount = size;
@@ -144,22 +148,22 @@ status_t AudioRecord::set(
}
// these below should probably come from the audioFlinger too...
if (format == 0) {
- format = AudioSystem::PCM_16_BIT;
+ format = AUDIO_FORMAT_PCM_16_BIT;
}
// validate parameters
- if (!AudioSystem::isValidFormat(format)) {
+ if (!audio_is_valid_format(format)) {
LOGE("Invalid format");
return BAD_VALUE;
}
- if (!AudioSystem::isInputChannel(channels)) {
+ if (!audio_is_input_channel(channels)) {
return BAD_VALUE;
}
- int channelCount = AudioSystem::popCount(channels);
+ int channelCount = popcount(channels);
audio_io_handle_t input = AudioSystem::getInput(inputSource,
- sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
+ sampleRate, format, channels, (audio_in_acoustics_t)flags);
if (input == 0) {
LOGE("Could not get audio input for record source %d", inputSource);
return BAD_VALUE;
@@ -253,8 +257,8 @@ uint32_t AudioRecord::frameCount() const
int AudioRecord::frameSize() const
{
- if (AudioSystem::isLinearPCM(mFormat)) {
- return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ if (audio_is_linear_pcm(mFormat)) {
+ return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
} else {
return sizeof(uint8_t);
}
@@ -299,7 +303,7 @@ status_t AudioRecord::start()
ret = mAudioRecord->start();
cblk->lock.lock();
if (ret == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
}
}
if (cblk->flags & CBLK_INVALID_MSK) {
@@ -467,7 +471,7 @@ status_t AudioRecord::openRecord_l(
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->flags &= ~CBLK_DIRECTION_MSK;
+ android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
return NO_ERROR;
@@ -522,7 +526,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
result = mAudioRecord->start();
cblk->lock.lock();
if (result == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
create_new_record:
result = AudioRecord::restoreRecord_l(cblk);
}
@@ -586,7 +590,7 @@ audio_io_handle_t AudioRecord::getInput_l()
mInput = AudioSystem::getInput(mInputSource,
mCblk->sampleRate,
mFormat, mChannels,
- (AudioSystem::audio_in_acoustics)mFlags);
+ (audio_in_acoustics_t)mFlags);
return mInput;
}
@@ -722,9 +726,8 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
// Manage overrun callback
if (mActive && (cblk->framesAvailable() == 0)) {
LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
- if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
+ if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
mCbf(EVENT_OVERRUN, mUserData, 0);
- cblk->flags |= CBLK_UNDERRUN_ON;
}
}
@@ -743,10 +746,8 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
{
status_t result;
- if (!(cblk->flags & CBLK_RESTORING_MSK)) {
+ if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
LOGW("dead IAudioRecord, creating a new one");
-
- cblk->flags |= CBLK_RESTORING_ON;
// signal old cblk condition so that other threads waiting for available buffers stop
// waiting now
cblk->cv.broadcast();
@@ -765,10 +766,8 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
}
// signal old cblk condition for other threads waiting for restore completion
- cblk->lock.lock();
- cblk->flags |= CBLK_RESTORED_MSK;
+ android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
cblk->cv.broadcast();
- cblk->lock.unlock();
} else {
if (!(cblk->flags & CBLK_RESTORED_MSK)) {
LOGW("dead IAudioRecord, waiting for a new one to be created");
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 2f694ba..e08a55b 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -23,6 +23,8 @@
#include <media/IAudioPolicyService.h>
#include <math.h>
+#include <hardware/audio.h>
+
// ----------------------------------------------------------------------------
// the sim build doesn't have gettid
@@ -45,7 +47,7 @@ DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSyst
// Cached values for recording queries
uint32_t AudioSystem::gPrevInSamplingRate = 16000;
-int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
+int AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT;
int AudioSystem::gPrevInChannelCount = 1;
size_t AudioSystem::gInBuffSize = 0;
@@ -127,7 +129,7 @@ status_t AudioSystem::getMasterMute(bool* mute)
status_t AudioSystem::setStreamVolume(int stream, float value, int output)
{
- if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
af->setStreamVolume(stream, value, output);
@@ -136,7 +138,7 @@ status_t AudioSystem::setStreamVolume(int stream, float value, int output)
status_t AudioSystem::setStreamMute(int stream, bool mute)
{
- if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
af->setStreamMute(stream, mute);
@@ -145,7 +147,7 @@ status_t AudioSystem::setStreamMute(int stream, bool mute)
status_t AudioSystem::getStreamVolume(int stream, float* volume, int output)
{
- if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
*volume = af->streamVolume(stream, output);
@@ -154,7 +156,7 @@ status_t AudioSystem::getStreamVolume(int stream, float* volume, int output)
status_t AudioSystem::getStreamMute(int stream, bool* mute)
{
- if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
*mute = af->streamMute(stream);
@@ -163,7 +165,7 @@ status_t AudioSystem::getStreamMute(int stream, bool* mute)
status_t AudioSystem::setMode(int mode)
{
- if (mode >= NUM_MODES) return BAD_VALUE;
+ if (mode >= AUDIO_MODE_CNT) return BAD_VALUE;
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->setMode(mode);
@@ -213,11 +215,11 @@ status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
OutputDescriptor *outputDesc;
audio_io_handle_t output;
- if (streamType == DEFAULT) {
- streamType = MUSIC;
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
}
- output = getOutput((stream_type)streamType);
+ output = getOutput((audio_stream_type_t)streamType);
if (output == 0) {
return PERMISSION_DENIED;
}
@@ -246,11 +248,11 @@ status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
OutputDescriptor *outputDesc;
audio_io_handle_t output;
- if (streamType == DEFAULT) {
- streamType = MUSIC;
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
}
- output = getOutput((stream_type)streamType);
+ output = getOutput((audio_stream_type_t)streamType);
if (output == 0) {
return PERMISSION_DENIED;
}
@@ -277,11 +279,11 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
OutputDescriptor *outputDesc;
audio_io_handle_t output;
- if (streamType == DEFAULT) {
- streamType = MUSIC;
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
}
- output = getOutput((stream_type)streamType);
+ output = getOutput((audio_stream_type_t)streamType);
if (output == 0) {
return PERMISSION_DENIED;
}
@@ -338,11 +340,11 @@ status_t AudioSystem::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- if (stream == DEFAULT) {
- stream = MUSIC;
+ if (stream == AUDIO_STREAM_DEFAULT) {
+ stream = AUDIO_STREAM_MUSIC;
}
- return af->getRenderPosition(halFrames, dspFrames, getOutput((stream_type)stream));
+ return af->getRenderPosition(halFrames, dspFrames, getOutput((audio_stream_type_t)stream));
}
unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
@@ -455,10 +457,10 @@ void AudioSystem::setErrorCallback(audio_error_callback cb) {
bool AudioSystem::routedToA2dpOutput(int streamType) {
switch(streamType) {
- case MUSIC:
- case VOICE_CALL:
- case BLUETOOTH_SCO:
- case SYSTEM:
+ case AUDIO_STREAM_MUSIC:
+ case AUDIO_STREAM_VOICE_CALL:
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ case AUDIO_STREAM_SYSTEM:
return true;
default:
return false;
@@ -497,9 +499,9 @@ const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
return gAudioPolicyService;
}
-status_t AudioSystem::setDeviceConnectionState(audio_devices device,
- device_connection_state state,
- const char *device_address)
+status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
@@ -507,11 +509,11 @@ status_t AudioSystem::setDeviceConnectionState(audio_devices device,
return aps->setDeviceConnectionState(device, state, device_address);
}
-AudioSystem::device_connection_state AudioSystem::getDeviceConnectionState(audio_devices device,
+audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
const char *device_address)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return DEVICE_STATE_UNAVAILABLE;
+ if (aps == 0) return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
return aps->getDeviceConnectionState(device, device_address);
}
@@ -531,26 +533,26 @@ status_t AudioSystem::setRingerMode(uint32_t mode, uint32_t mask)
return aps->setRingerMode(mode, mask);
}
-status_t AudioSystem::setForceUse(force_use usage, forced_config config)
+status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setForceUse(usage, config);
}
-AudioSystem::forced_config AudioSystem::getForceUse(force_use usage)
+audio_policy_forced_cfg_t AudioSystem::getForceUse(audio_policy_force_use_t usage)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return FORCE_NONE;
+ if (aps == 0) return AUDIO_POLICY_FORCE_NONE;
return aps->getForceUse(usage);
}
-audio_io_handle_t AudioSystem::getOutput(stream_type stream,
+audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- output_flags flags)
+ audio_policy_output_flags_t flags)
{
audio_io_handle_t output = 0;
// Do not use stream to output map cache if the direct output
@@ -561,9 +563,9 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
// be reworked for proper operation with direct outputs. This code is too specific
// to the first use case we want to cover (Voice Recognition and Voice Dialer over
// Bluetooth SCO
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0 &&
- ((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) ||
- channels != AudioSystem::CHANNEL_OUT_MONO ||
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0 &&
+ ((stream != AUDIO_STREAM_VOICE_CALL && stream != AUDIO_STREAM_BLUETOOTH_SCO) ||
+ channels != AUDIO_CHANNEL_OUT_MONO ||
(samplingRate != 8000 && samplingRate != 16000))) {
Mutex::Autolock _l(gLock);
output = AudioSystem::gStreamOutputMap.valueFor(stream);
@@ -573,7 +575,7 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
output = aps->getOutput(stream, samplingRate, format, channels, flags);
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0) {
Mutex::Autolock _l(gLock);
AudioSystem::gStreamOutputMap.add(stream, output);
}
@@ -582,7 +584,7 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
}
status_t AudioSystem::startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -591,7 +593,7 @@ status_t AudioSystem::startOutput(audio_io_handle_t output,
}
status_t AudioSystem::stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -610,7 +612,7 @@ audio_io_handle_t AudioSystem::getInput(int inputSource,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- audio_in_acoustics acoustics)
+ audio_in_acoustics_t acoustics)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
@@ -638,7 +640,7 @@ void AudioSystem::releaseInput(audio_io_handle_t input)
aps->releaseInput(input);
}
-status_t AudioSystem::initStreamVolume(stream_type stream,
+status_t AudioSystem::initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax)
{
@@ -647,28 +649,28 @@ status_t AudioSystem::initStreamVolume(stream_type stream,
return aps->initStreamVolume(stream, indexMin, indexMax);
}
-status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)
+status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, int index)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index);
}
-status_t AudioSystem::getStreamVolumeIndex(stream_type stream, int *index)
+status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream, int *index)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->getStreamVolumeIndex(stream, index);
}
-uint32_t AudioSystem::getStrategyForStream(AudioSystem::stream_type stream)
+uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
return aps->getStrategyForStream(stream);
}
-uint32_t AudioSystem::getDevicesForStream(AudioSystem::stream_type stream)
+uint32_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return 0;
@@ -717,276 +719,5 @@ void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
LOGW("AudioPolicyService server died!");
}
-// ---------------------------------------------------------------------------
-
-
-// use emulated popcount optimization
-// http://www.df.lth.se/~john_e/gems/gem002d.html
-uint32_t AudioSystem::popCount(uint32_t u)
-{
- u = ((u&0x55555555) + ((u>>1)&0x55555555));
- u = ((u&0x33333333) + ((u>>2)&0x33333333));
- u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
- u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
- u = ( u&0x0000ffff) + (u>>16);
- return u;
-}
-
-bool AudioSystem::isOutputDevice(audio_devices device)
-{
- if ((popCount(device) == 1 ) &&
- ((device & ~AudioSystem::DEVICE_OUT_ALL) == 0)) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isInputDevice(audio_devices device)
-{
- if ((popCount(device) == 1 ) &&
- ((device & ~AudioSystem::DEVICE_IN_ALL) == 0)) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isA2dpDevice(audio_devices device)
-{
- if ((popCount(device) == 1 ) &&
- (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
- AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER))) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isBluetoothScoDevice(audio_devices device)
-{
- if ((popCount(device) == 1 ) &&
- (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO |
- AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
- AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
- AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET))) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isLowVisibility(stream_type stream)
-{
- if (stream == AudioSystem::SYSTEM ||
- stream == AudioSystem::NOTIFICATION ||
- stream == AudioSystem::RING) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isInputChannel(uint32_t channel)
-{
- if ((channel & ~AudioSystem::CHANNEL_IN_ALL) == 0) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isOutputChannel(uint32_t channel)
-{
- if ((channel & ~AudioSystem::CHANNEL_OUT_ALL) == 0) {
- return true;
- } else {
- return false;
- }
-}
-
-bool AudioSystem::isValidFormat(uint32_t format)
-{
- switch (format & MAIN_FORMAT_MASK) {
- case PCM:
- case MP3:
- case AMR_NB:
- case AMR_WB:
- case AAC:
- case HE_AAC_V1:
- case HE_AAC_V2:
- case VORBIS:
- return true;
- default:
- return false;
- }
-}
-
-bool AudioSystem::isLinearPCM(uint32_t format)
-{
- switch (format) {
- case PCM_16_BIT:
- case PCM_8_BIT:
- return true;
- default:
- return false;
- }
-}
-
-//------------------------- AudioParameter class implementation ---------------
-
-const char *AudioParameter::keyRouting = "routing";
-const char *AudioParameter::keySamplingRate = "sampling_rate";
-const char *AudioParameter::keyFormat = "format";
-const char *AudioParameter::keyChannels = "channels";
-const char *AudioParameter::keyFrameCount = "frame_count";
-const char *AudioParameter::keyInputSource = "input_source";
-
-AudioParameter::AudioParameter(const String8& keyValuePairs)
-{
- char *str = new char[keyValuePairs.length()+1];
- mKeyValuePairs = keyValuePairs;
-
- strcpy(str, keyValuePairs.string());
- char *pair = strtok(str, ";");
- while (pair != NULL) {
- if (strlen(pair) != 0) {
- size_t eqIdx = strcspn(pair, "=");
- String8 key = String8(pair, eqIdx);
- String8 value;
- if (eqIdx == strlen(pair)) {
- value = String8("");
- } else {
- value = String8(pair + eqIdx + 1);
- }
- if (mParameters.indexOfKey(key) < 0) {
- mParameters.add(key, value);
- } else {
- mParameters.replaceValueFor(key, value);
- }
- } else {
- LOGV("AudioParameter() cstor empty key value pair");
- }
- pair = strtok(NULL, ";");
- }
-
- delete[] str;
-}
-
-AudioParameter::~AudioParameter()
-{
- mParameters.clear();
-}
-
-String8 AudioParameter::toString()
-{
- String8 str = String8("");
-
- size_t size = mParameters.size();
- for (size_t i = 0; i < size; i++) {
- str += mParameters.keyAt(i);
- str += "=";
- str += mParameters.valueAt(i);
- if (i < (size - 1)) str += ";";
- }
- return str;
-}
-
-status_t AudioParameter::add(const String8& key, const String8& value)
-{
- if (mParameters.indexOfKey(key) < 0) {
- mParameters.add(key, value);
- return NO_ERROR;
- } else {
- mParameters.replaceValueFor(key, value);
- return ALREADY_EXISTS;
- }
-}
-
-status_t AudioParameter::addInt(const String8& key, const int value)
-{
- char str[12];
- if (snprintf(str, 12, "%d", value) > 0) {
- String8 str8 = String8(str);
- return add(key, str8);
- } else {
- return BAD_VALUE;
- }
-}
-
-status_t AudioParameter::addFloat(const String8& key, const float value)
-{
- char str[23];
- if (snprintf(str, 23, "%.10f", value) > 0) {
- String8 str8 = String8(str);
- return add(key, str8);
- } else {
- return BAD_VALUE;
- }
-}
-
-status_t AudioParameter::remove(const String8& key)
-{
- if (mParameters.indexOfKey(key) >= 0) {
- mParameters.removeItem(key);
- return NO_ERROR;
- } else {
- return BAD_VALUE;
- }
-}
-
-status_t AudioParameter::get(const String8& key, String8& value)
-{
- if (mParameters.indexOfKey(key) >= 0) {
- value = mParameters.valueFor(key);
- return NO_ERROR;
- } else {
- return BAD_VALUE;
- }
-}
-
-status_t AudioParameter::getInt(const String8& key, int& value)
-{
- String8 str8;
- status_t result = get(key, str8);
- value = 0;
- if (result == NO_ERROR) {
- int val;
- if (sscanf(str8.string(), "%d", &val) == 1) {
- value = val;
- } else {
- result = INVALID_OPERATION;
- }
- }
- return result;
-}
-
-status_t AudioParameter::getFloat(const String8& key, float& value)
-{
- String8 str8;
- status_t result = get(key, str8);
- value = 0;
- if (result == NO_ERROR) {
- float val;
- if (sscanf(str8.string(), "%f", &val) == 1) {
- value = val;
- } else {
- result = INVALID_OPERATION;
- }
- }
- return result;
-}
-
-status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
-{
- if (mParameters.size() > index) {
- key = mParameters.keyAt(index);
- value = mParameters.valueAt(index);
- return NO_ERROR;
- } else {
- return BAD_VALUE;
- }
-}
}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 8d8f67b..2673df9 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -35,6 +35,12 @@
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
+#include <utils/Atomic.h>
+
+#include <cutils/bitops.h>
+
+#include <hardware/audio.h>
+#include <hardware/audio_policy.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -164,39 +170,41 @@ status_t AudioTrack::set(
}
// handle default values first.
- if (streamType == AudioSystem::DEFAULT) {
- streamType = AudioSystem::MUSIC;
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
}
if (sampleRate == 0) {
sampleRate = afSampleRate;
}
// these below should probably come from the audioFlinger too...
if (format == 0) {
- format = AudioSystem::PCM_16_BIT;
+ format = AUDIO_FORMAT_PCM_16_BIT;
}
if (channels == 0) {
- channels = AudioSystem::CHANNEL_OUT_STEREO;
+ channels = AUDIO_CHANNEL_OUT_STEREO;
}
// validate parameters
- if (!AudioSystem::isValidFormat(format)) {
+ if (!audio_is_valid_format(format)) {
LOGE("Invalid format");
return BAD_VALUE;
}
// force direct flag if format is not linear PCM
- if (!AudioSystem::isLinearPCM(format)) {
- flags |= AudioSystem::OUTPUT_FLAG_DIRECT;
+ if (!audio_is_linear_pcm(format)) {
+ flags |= AUDIO_POLICY_OUTPUT_FLAG_DIRECT;
}
- if (!AudioSystem::isOutputChannel(channels)) {
+ if (!audio_is_output_channel(channels)) {
LOGE("Invalid channel mask");
return BAD_VALUE;
}
- uint32_t channelCount = AudioSystem::popCount(channels);
+ uint32_t channelCount = popcount(channels);
- audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
- sampleRate, format, channels, (AudioSystem::output_flags)flags);
+ audio_io_handle_t output = AudioSystem::getOutput(
+ (audio_stream_type_t)streamType,
+ sampleRate,format, channels,
+ (audio_policy_output_flags_t)flags);
if (output == 0) {
LOGE("Could not get audio output for stream type %d", streamType);
@@ -289,8 +297,8 @@ uint32_t AudioTrack::frameCount() const
int AudioTrack::frameSize() const
{
- if (AudioSystem::isLinearPCM(mFormat)) {
- return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ if (audio_is_linear_pcm(mFormat)) {
+ return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
} else {
return sizeof(uint8_t);
}
@@ -329,9 +337,10 @@ void AudioTrack::start()
if (mActive == 0) {
mActive = 1;
mNewPosition = cblk->server + mUpdatePeriod;
+ cblk->lock.lock();
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
- cblk->flags &= ~CBLK_DISABLED_ON;
+ android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
if (t != 0) {
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
@@ -339,13 +348,12 @@ void AudioTrack::start()
}
LOGV("start %p before lock cblk %p", this, mCblk);
- cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
status = mAudioTrack->start();
cblk->lock.lock();
if (status == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
}
}
if (cblk->flags & CBLK_INVALID_MSK) {
@@ -546,12 +554,13 @@ status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCou
}
if (loopStart >= loopEnd ||
- loopEnd - loopStart > cblk->frameCount) {
+ loopEnd - loopStart > cblk->frameCount ||
+ cblk->server > loopStart) {
LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
return BAD_VALUE;
}
- if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
+ if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
loopStart, loopEnd, cblk->frameCount);
return BAD_VALUE;
@@ -635,7 +644,7 @@ status_t AudioTrack::setPosition(uint32_t position)
if (position > mCblk->user) return BAD_VALUE;
mCblk->server = position;
- mCblk->flags |= CBLK_FORCEREADY_ON;
+ android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags);
return NO_ERROR;
}
@@ -671,8 +680,8 @@ audio_io_handle_t AudioTrack::getOutput()
// must be called with mLock held
audio_io_handle_t AudioTrack::getOutput_l()
{
- return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType,
- mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
+ return AudioSystem::getOutput((audio_stream_type_t)mStreamType,
+ mCblk->sampleRate, mFormat, mChannels, (audio_policy_output_flags_t)mFlags);
}
int AudioTrack::getSessionId()
@@ -725,7 +734,7 @@ status_t AudioTrack::createTrack_l(
}
mNotificationFramesAct = mNotificationFramesReq;
- if (!AudioSystem::isLinearPCM(format)) {
+ if (!audio_is_linear_pcm(format)) {
if (sharedBuffer != 0) {
frameCount = sharedBuffer->size();
}
@@ -792,7 +801,7 @@ status_t AudioTrack::createTrack_l(
mCblkMemory.clear();
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
- mCblk->flags |= CBLK_DIRECTION_OUT;
+ android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
if (sharedBuffer == 0) {
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
} else {
@@ -825,6 +834,12 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
uint32_t framesAvail = cblk->framesAvailable();
+ cblk->lock.lock();
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ goto create_new_track;
+ }
+ cblk->lock.unlock();
+
if (framesAvail == 0) {
cblk->lock.lock();
goto start_loop_here;
@@ -866,7 +881,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
result = mAudioTrack->start();
cblk->lock.lock();
if (result == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
create_new_track:
result = restoreTrack_l(cblk, false);
}
@@ -893,7 +908,7 @@ create_new_track:
// restart track if it was disabled by audioflinger due to previous underrun
if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
- cblk->flags &= ~CBLK_DISABLED_ON;
+ android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
LOGW("obtainBuffer() track %p disabled, restarting", this);
mAudioTrack->start();
}
@@ -915,8 +930,8 @@ create_new_track:
audioBuffer->channelCount = mChannelCount;
audioBuffer->frameCount = framesReq;
audioBuffer->size = framesReq * cblk->frameSize;
- if (AudioSystem::isLinearPCM(mFormat)) {
- audioBuffer->format = AudioSystem::PCM_16_BIT;
+ if (audio_is_linear_pcm(mFormat)) {
+ audioBuffer->format = AUDIO_FORMAT_PCM_16_BIT;
} else {
audioBuffer->format = mFormat;
}
@@ -957,9 +972,10 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
ssize_t written = 0;
const int8_t *src = (const int8_t *)buffer;
Buffer audioBuffer;
+ size_t frameSz = (size_t)frameSize();
do {
- audioBuffer.frameCount = userSize/frameSize();
+ audioBuffer.frameCount = userSize/frameSz;
// Calling obtainBuffer() with a negative wait count causes
// an (almost) infinite wait time.
@@ -973,7 +989,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
size_t toWrite;
- if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) {
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
// Divide capacity by 2 to take expansion into account
toWrite = audioBuffer.size>>1;
// 8 to 16 bit conversion
@@ -991,7 +1007,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
written += toWrite;
releaseBuffer(&audioBuffer);
- } while (userSize);
+ } while (userSize >= frameSz);
return written;
}
@@ -1013,14 +1029,13 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
mLock.unlock();
// Manage underrun callback
- if (mActive && (cblk->framesReady() == 0)) {
+ if (mActive && (cblk->framesAvailable() == cblk->frameCount)) {
LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
- if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
+ if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
mCbf(EVENT_UNDERRUN, mUserData, 0);
if (cblk->server == cblk->frameCount) {
mCbf(EVENT_BUFFER_END, mUserData, 0);
}
- cblk->flags |= CBLK_UNDERRUN_ON;
if (mSharedBuffer != 0) return false;
}
}
@@ -1077,7 +1092,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
// Divide buffer size by 2 to take into account the expansion
// due to 8 to 16 bit conversion: the callback must fill only half
// of the destination buffer
- if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) {
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
audioBuffer.size >>= 1;
}
@@ -1096,7 +1111,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
}
if (writtenSize > reqSize) writtenSize = reqSize;
- if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) {
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
// 8 to 16 bit conversion
const int8_t *src = audioBuffer.i8 + writtenSize-1;
int count = writtenSize;
@@ -1134,11 +1149,10 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
{
status_t result;
- if (!(cblk->flags & CBLK_RESTORING_MSK)) {
+ if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
LOGW("dead IAudioTrack, creating a new one from %s",
fromStart ? "start()" : "obtainBuffer()");
- cblk->flags |= CBLK_RESTORING_ON;
// signal old cblk condition so that other threads waiting for available buffers stop
// waiting now
cblk->cv.broadcast();
@@ -1158,10 +1172,20 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
false);
if (result == NO_ERROR) {
+ // restore write index and set other indexes to reflect empty buffer status
+ mCblk->user = cblk->user;
+ mCblk->server = cblk->user;
+ mCblk->userBase = cblk->user;
+ mCblk->serverBase = cblk->user;
+ // restore loop: this is not guaranteed to succeed if new frame count is not
+ // compatible with loop length
+ setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount);
if (!fromStart) {
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
}
- result = mAudioTrack->start();
+ if (mActive) {
+ result = mAudioTrack->start();
+ }
if (fromStart && result == NO_ERROR) {
mNewPosition = mCblk->server + mUpdatePeriod;
}
@@ -1171,10 +1195,8 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
}
// signal old cblk condition for other threads waiting for restore completion
- cblk->lock.lock();
- cblk->flags |= CBLK_RESTORED_MSK;
+ android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
cblk->cv.broadcast();
- cblk->lock.unlock();
} else {
if (!(cblk->flags & CBLK_RESTORED_MSK)) {
LOGW("dead IAudioTrack, waiting for a new one");
@@ -1248,11 +1270,12 @@ void AudioTrack::AudioTrackThread::onFirstRef()
// =========================================================================
+
audio_track_cblk_t::audio_track_cblk_t()
: lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
userBase(0), serverBase(0), buffers(0), frameCount(0),
loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
- flags(0), sendLevel(0)
+ sendLevel(0), flags(0)
{
}
@@ -1279,25 +1302,17 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
this->user = u;
// Clear flow control error condition as new data has been written/read to/from buffer.
- flags &= ~CBLK_UNDERRUN_MSK;
+ if (flags & CBLK_UNDERRUN_MSK) {
+ android_atomic_and(~CBLK_UNDERRUN_MSK, &flags);
+ }
return u;
}
bool audio_track_cblk_t::stepServer(uint32_t frameCount)
{
- // the code below simulates lock-with-timeout
- // we MUST do this to protect the AudioFlinger server
- // as this lock is shared with the client.
- status_t err;
-
- err = lock.tryLock();
- if (err == -EBUSY) { // just wait a bit
- usleep(1000);
- err = lock.tryLock();
- }
- if (err != NO_ERROR) {
- // probably, the client just died.
+ if (!tryLock()) {
+ LOGW("stepServer() could not lock cblk");
return false;
}
@@ -1374,18 +1389,42 @@ uint32_t audio_track_cblk_t::framesReady()
if (u < loopEnd) {
return u - s;
} else {
- Mutex::Autolock _l(lock);
+ // do not block on mutex shared with client on AudioFlinger side
+ if (!tryLock()) {
+ LOGW("framesReady() could not lock cblk");
+ return 0;
+ }
+ uint32_t frames = UINT_MAX;
if (loopCount >= 0) {
- return (loopEnd - loopStart)*loopCount + u - s;
- } else {
- return UINT_MAX;
+ frames = (loopEnd - loopStart)*loopCount + u - s;
}
+ lock.unlock();
+ return frames;
}
} else {
return s - u;
}
}
+bool audio_track_cblk_t::tryLock()
+{
+ // the code below simulates lock-with-timeout
+ // we MUST do this to protect the AudioFlinger server
+ // as this lock is shared with the client.
+ status_t err;
+
+ err = lock.tryLock();
+ if (err == -EBUSY) { // just wait a bit
+ usleep(1000);
+ err = lock.tryLock();
+ }
+ if (err != NO_ERROR) {
+ // probably, the client just died.
+ return false;
+ }
+ return true;
+}
+
// -------------------------------------------------------------------------
}; // namespace android
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index b89a278..88a9ae0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -25,6 +25,8 @@
#include <media/IAudioPolicyService.h>
+#include <hardware/audio.h>
+
namespace android {
enum {
@@ -62,8 +64,8 @@ public:
}
virtual status_t setDeviceConnectionState(
- AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
+ audio_devices_t device,
+ audio_policy_dev_state_t state,
const char *device_address)
{
Parcel data, reply;
@@ -75,8 +77,8 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual AudioSystem::device_connection_state getDeviceConnectionState(
- AudioSystem::audio_devices device,
+ virtual audio_policy_dev_state_t getDeviceConnectionState(
+ audio_devices_t device,
const char *device_address)
{
Parcel data, reply;
@@ -84,7 +86,7 @@ public:
data.writeInt32(static_cast <uint32_t>(device));
data.writeCString(device_address);
remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply);
- return static_cast <AudioSystem::device_connection_state>(reply.readInt32());
+ return static_cast <audio_policy_dev_state_t>(reply.readInt32());
}
virtual status_t setPhoneState(int state)
@@ -106,7 +108,7 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -116,21 +118,21 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage)
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(static_cast <uint32_t>(usage));
remote()->transact(GET_FORCE_USE, data, &reply);
- return static_cast <AudioSystem::forced_config> (reply.readInt32());
+ return static_cast <audio_policy_forced_cfg_t> (reply.readInt32());
}
virtual audio_io_handle_t getOutput(
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- AudioSystem::output_flags flags)
+ audio_policy_output_flags_t flags)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -144,7 +146,7 @@ public:
}
virtual status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
Parcel data, reply;
@@ -157,7 +159,7 @@ public:
}
virtual status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
Parcel data, reply;
@@ -182,7 +184,7 @@ public:
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- AudioSystem::audio_in_acoustics acoustics)
+ audio_in_acoustics_t acoustics)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -221,7 +223,7 @@ public:
remote()->transact(RELEASE_INPUT, data, &reply);
}
- virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax)
{
@@ -234,7 +236,7 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, int index)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -244,7 +246,7 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -255,7 +257,7 @@ public:
return static_cast <status_t> (reply.readInt32());
}
- virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream)
+ virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -264,7 +266,7 @@ public:
return reply.readInt32();
}
- virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream)
+ virtual uint32_t getDevicesForStream(audio_stream_type_t stream)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -330,10 +332,10 @@ status_t BnAudioPolicyService::onTransact(
switch(code) {
case SET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::audio_devices device =
- static_cast <AudioSystem::audio_devices>(data.readInt32());
- AudioSystem::device_connection_state state =
- static_cast <AudioSystem::device_connection_state>(data.readInt32());
+ audio_devices_t device =
+ static_cast <audio_devices_t>(data.readInt32());
+ audio_policy_dev_state_t state =
+ static_cast <audio_policy_dev_state_t>(data.readInt32());
const char *device_address = data.readCString();
reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
state,
@@ -343,8 +345,8 @@ status_t BnAudioPolicyService::onTransact(
case GET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::audio_devices device =
- static_cast<AudioSystem::audio_devices> (data.readInt32());
+ audio_devices_t device =
+ static_cast<audio_devices_t> (data.readInt32());
const char *device_address = data.readCString();
reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
device_address)));
@@ -367,29 +369,29 @@ status_t BnAudioPolicyService::onTransact(
case SET_FORCE_USE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
- AudioSystem::forced_config config =
- static_cast <AudioSystem::forced_config>(data.readInt32());
+ audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>(data.readInt32());
+ audio_policy_forced_cfg_t config =
+ static_cast <audio_policy_forced_cfg_t>(data.readInt32());
reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
return NO_ERROR;
} break;
case GET_FORCE_USE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+ audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>(data.readInt32());
reply->writeInt32(static_cast <uint32_t>(getForceUse(usage)));
return NO_ERROR;
} break;
case GET_OUTPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
uint32_t samplingRate = data.readInt32();
uint32_t format = data.readInt32();
uint32_t channels = data.readInt32();
- AudioSystem::output_flags flags =
- static_cast <AudioSystem::output_flags>(data.readInt32());
+ audio_policy_output_flags_t flags =
+ static_cast <audio_policy_output_flags_t>(data.readInt32());
audio_io_handle_t output = getOutput(stream,
samplingRate,
@@ -406,7 +408,7 @@ status_t BnAudioPolicyService::onTransact(
uint32_t stream = data.readInt32();
int session = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(startOutput(output,
- (AudioSystem::stream_type)stream,
+ (audio_stream_type_t)stream,
session)));
return NO_ERROR;
} break;
@@ -417,7 +419,7 @@ status_t BnAudioPolicyService::onTransact(
uint32_t stream = data.readInt32();
int session = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
- (AudioSystem::stream_type)stream,
+ (audio_stream_type_t)stream,
session)));
return NO_ERROR;
} break;
@@ -435,8 +437,8 @@ status_t BnAudioPolicyService::onTransact(
uint32_t samplingRate = data.readInt32();
uint32_t format = data.readInt32();
uint32_t channels = data.readInt32();
- AudioSystem::audio_in_acoustics acoustics =
- static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+ audio_in_acoustics_t acoustics =
+ static_cast <audio_in_acoustics_t>(data.readInt32());
audio_io_handle_t input = getInput(inputSource,
samplingRate,
format,
@@ -469,8 +471,8 @@ status_t BnAudioPolicyService::onTransact(
case INIT_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
int indexMin = data.readInt32();
int indexMax = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
@@ -479,8 +481,8 @@ status_t BnAudioPolicyService::onTransact(
case SET_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
int index = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
return NO_ERROR;
@@ -488,8 +490,8 @@ status_t BnAudioPolicyService::onTransact(
case GET_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
int index;
status_t status = getStreamVolumeIndex(stream, &index);
reply->writeInt32(index);
@@ -499,16 +501,16 @@ status_t BnAudioPolicyService::onTransact(
case GET_STRATEGY_FOR_STREAM: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
reply->writeInt32(getStrategyForStream(stream));
return NO_ERROR;
} break;
case GET_DEVICES_FOR_STREAM: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream =
- static_cast <AudioSystem::stream_type>(data.readInt32());
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
reply->writeInt32(static_cast <int>(getDevicesForStream(stream)));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index d5298c9..ebe821f 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -20,6 +20,7 @@
#include <binder/Parcel.h>
#include <SkBitmap.h>
#include <media/IMediaMetadataRetriever.h>
+#include <utils/String8.h>
// The binder is supposed to propagate the scheduler group across
// the binder interface so that remote calls are executed with
@@ -102,11 +103,24 @@ public:
remote()->transact(DISCONNECT, data, &reply);
}
- status_t setDataSource(const char* srcUrl)
+ status_t setDataSource(
+ const char *srcUrl, const KeyedVector<String8, String8> *headers)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
data.writeCString(srcUrl);
+
+ if (headers == NULL) {
+ data.writeInt32(0);
+ } else {
+ // serialize the headers
+ data.writeInt32(headers->size());
+ for (size_t i = 0; i < headers->size(); ++i) {
+ data.writeString8(headers->keyAt(i));
+ data.writeString8(headers->valueAt(i));
+ }
+ }
+
remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
return reply.readInt32();
}
@@ -188,7 +202,18 @@ status_t BnMediaMetadataRetriever::onTransact(
case SET_DATA_SOURCE_URL: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
const char* srcUrl = data.readCString();
- reply->writeInt32(setDataSource(srcUrl));
+
+ KeyedVector<String8, String8> headers;
+ int32_t numHeaders = data.readInt32();
+ for (int i = 0; i < numHeaders; ++i) {
+ String8 key = data.readString8();
+ String8 value = data.readString8();
+ headers.add(key, value);
+ }
+
+ reply->writeInt32(
+ setDataSource(srcUrl, numHeaders > 0 ? &headers : NULL));
+
return NO_ERROR;
} break;
case SET_DATA_SOURCE_FD: {
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 2399216..76a8a91 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -48,6 +48,8 @@ enum {
SET_AUX_EFFECT_SEND_LEVEL,
ATTACH_AUX_EFFECT,
SET_VIDEO_SURFACETEXTURE,
+ SET_PARAMETER,
+ GET_PARAMETER,
};
class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -192,8 +194,9 @@ public:
}
status_t invoke(const Parcel& request, Parcel *reply)
- { // Avoid doing any extra copy. The interface descriptor should
- // have been set by MediaPlayer.java.
+ {
+ // Avoid doing any extra copy. The interface descriptor should
+ // have been set by MediaPlayer.java.
return remote()->transact(INVOKE, request, reply);
}
@@ -235,6 +238,26 @@ public:
return reply.readInt32();
}
+ status_t setParameter(int key, const Parcel& request)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ if (request.dataSize() > 0) {
+ data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
+ }
+ remote()->transact(SET_PARAMETER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getParameter(int key, Parcel *reply)
+ {
+ Parcel data;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ return remote()->transact(GET_PARAMETER, data, reply);
+ }
+
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -334,8 +357,8 @@ status_t BnMediaPlayer::onTransact(
} break;
case INVOKE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
- invoke(data, reply);
- return NO_ERROR;
+ status_t result = invoke(data, reply);
+ return result;
} break;
case SET_METADATA_FILTER: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
@@ -360,6 +383,23 @@ status_t BnMediaPlayer::onTransact(
reply->writeInt32(attachAuxEffect(data.readInt32()));
return NO_ERROR;
} break;
+ case SET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int key = data.readInt32();
+
+ Parcel request;
+ if (data.dataAvail() > 0) {
+ request.appendFrom(
+ const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
+ }
+ request.setDataPosition(0);
+ reply->writeInt32(setParameter(key, request));
+ return NO_ERROR;
+ } break;
+ case GET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ return getParameter(data.readInt32(), reply);
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp
index bf51829..1f135c4 100644
--- a/media/libmedia/IMediaPlayerClient.cpp
+++ b/media/libmedia/IMediaPlayerClient.cpp
@@ -35,13 +35,16 @@ public:
{
}
- virtual void notify(int msg, int ext1, int ext2)
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
data.writeInt32(msg);
data.writeInt32(ext1);
data.writeInt32(ext2);
+ if (obj && obj->dataSize() > 0) {
+ data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
+ }
remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -59,7 +62,12 @@ status_t BnMediaPlayerClient::onTransact(
int msg = data.readInt32();
int ext1 = data.readInt32();
int ext2 = data.readInt32();
- notify(msg, ext1, ext2);
+ Parcel obj;
+ if (data.dataAvail() > 0) {
+ obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
+ }
+
+ notify(msg, ext1, ext2, &obj);
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index ee9e1d8..88157d2 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -96,10 +96,10 @@ int JetPlayer::init()
// create the output AudioTrack
mAudioTrack = new AudioTrack();
- mAudioTrack->set(AudioSystem::MUSIC, //TODO parametrize this
+ mAudioTrack->set(AUDIO_STREAM_MUSIC, //TODO parametrize this
pLibConfig->sampleRate,
1, // format = PCM 16bits per sample,
- (pLibConfig->numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+ (pLibConfig->numChannels == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
mTrackBufferSize,
0);
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 4e22175..28c8642 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -135,20 +135,21 @@ status_t MediaScanner::doProcessDirectory(
}
if (type == DT_REG || type == DT_DIR) {
if (type == DT_DIR) {
+ bool childNoMedia = noMedia;
// set noMedia flag on directories with a name that starts with '.'
// for example, the Mac ".Trashes" directory
if (name[0] == '.')
- noMedia = true;
+ childNoMedia = true;
// report the directory to the client
if (stat(path, &statbuf) == 0) {
- client.scanFile(path, statbuf.st_mtime, 0, true, noMedia);
+ client.scanFile(path, statbuf.st_mtime, 0, true, childNoMedia);
}
// and now process its contents
strcat(fileSpot, "/");
int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
- noMedia, exceptionCheck, exceptionEnv);
+ childNoMedia, exceptionCheck, exceptionEnv);
if (err) {
// pass exceptions up - ignore other errors
if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
new file mode 100644
index 0000000..6a108ae
--- /dev/null
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011, 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/MemoryLeakTrackUtil.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * The code here originally resided in MediaPlayerService.cpp and was
+ * shamelessly copied over to support memory leak tracking from
+ * multiple places.
+ */
+namespace android {
+
+#if defined(__arm__)
+
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+// Use the String-class below instead of String8 to allocate all memory
+// beforehand and not reenter the heap while we are examining it...
+struct MyString8 {
+ static const size_t MAX_SIZE = 256 * 1024;
+
+ MyString8()
+ : mPtr((char *)malloc(MAX_SIZE)) {
+ *mPtr = '\0';
+ }
+
+ ~MyString8() {
+ free(mPtr);
+ }
+
+ void append(const char *s) {
+ strcat(mPtr, s);
+ }
+
+ const char *string() const {
+ return mPtr;
+ }
+
+ size_t size() const {
+ return strlen(mPtr);
+ }
+
+private:
+ char *mPtr;
+
+ MyString8(const MyString8 &);
+ MyString8 &operator=(const MyString8 &);
+};
+
+void dumpMemoryAddresses(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ MyString8 result;
+
+ typedef struct {
+ size_t size;
+ size_t dups;
+ intptr_t * backtrace;
+ } AllocEntry;
+
+ uint8_t *info = NULL;
+ size_t overallSize = 0;
+ size_t infoSize = 0;
+ size_t totalMemory = 0;
+ size_t backtraceSize = 0;
+
+ get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+ if (info) {
+ uint8_t *ptr = info;
+ size_t count = overallSize / infoSize;
+
+ snprintf(buffer, SIZE, " Allocation count %i\n", count);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
+ result.append(buffer);
+
+ AllocEntry * entries = new AllocEntry[count];
+
+ for (size_t i = 0; i < count; i++) {
+ // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+ AllocEntry *e = &entries[i];
+
+ e->size = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->dups = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+ ptr += sizeof(intptr_t) * backtraceSize;
+ }
+
+ // Now we need to sort the entries. They come sorted by size but
+ // not by stack trace which causes problems using diff.
+ bool moved;
+ do {
+ moved = false;
+ for (size_t i = 0; i < (count - 1); i++) {
+ AllocEntry *e1 = &entries[i];
+ AllocEntry *e2 = &entries[i+1];
+
+ bool swap = e1->size < e2->size;
+ if (e1->size == e2->size) {
+ for(size_t j = 0; j < backtraceSize; j++) {
+ if (e1->backtrace[j] == e2->backtrace[j]) {
+ continue;
+ }
+ swap = e1->backtrace[j] < e2->backtrace[j];
+ break;
+ }
+ }
+ if (swap) {
+ AllocEntry t = entries[i];
+ entries[i] = entries[i+1];
+ entries[i+1] = t;
+ moved = true;
+ }
+ }
+ } while (moved);
+
+ for (size_t i = 0; i < count; i++) {
+ AllocEntry *e = &entries[i];
+
+ snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
+ result.append(buffer);
+ for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+ if (ct) {
+ result.append(", ");
+ }
+ snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+ result.append(buffer);
+ }
+ result.append("\n");
+ }
+
+ delete[] entries;
+ free_malloc_leak_info(info);
+ }
+
+ write(fd, result.string(), result.size());
+}
+
+#else
+// Does nothing
+void dumpMemoryAddresses(int fd) {}
+
+#endif
+} // namespace android
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 82fe2d4..9f1b3d6 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1026,8 +1026,8 @@ bool ToneGenerator::initAudioTrack() {
mpAudioTrack->set(mStreamType,
0,
- AudioSystem::PCM_16_BIT,
- AudioSystem::CHANNEL_OUT_MONO,
+ AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_MONO,
0,
0,
audioCallback,
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 43571cf..366707c 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -24,6 +24,8 @@
#include <sys/types.h>
#include <limits.h>
+#include <cutils/bitops.h>
+
#include <media/Visualizer.h>
extern void fixed_fft_real(int n, int32_t *v);
@@ -127,7 +129,7 @@ status_t Visualizer::setCaptureSize(uint32_t size)
{
if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
size < VISUALIZER_CAPTURE_SIZE_MIN ||
- AudioSystem::popCount(size) != 1) {
+ popcount(size) != 1) {
return BAD_VALUE;
}
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 8dfcb3b..cee06ab 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -92,7 +92,8 @@ void MediaMetadataRetriever::disconnect()
}
}
-status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
+status_t MediaMetadataRetriever::setDataSource(
+ const char *srcUrl, const KeyedVector<String8, String8> *headers)
{
LOGV("setDataSource");
Mutex::Autolock _l(mLock);
@@ -105,7 +106,7 @@ status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
return UNKNOWN_ERROR;
}
LOGV("data source (%s)", srcUrl);
- return mRetriever->setDataSource(srcUrl);
+ return mRetriever->setDataSource(srcUrl, headers);
}
status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 0ee0249..28e07ff 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -37,6 +37,8 @@
#include <utils/KeyedVector.h>
#include <utils/String8.h>
+#include <hardware/audio.h>
+
namespace android {
MediaPlayer::MediaPlayer()
@@ -45,7 +47,7 @@ MediaPlayer::MediaPlayer()
mListener = NULL;
mCookie = NULL;
mDuration = -1;
- mStreamType = AudioSystem::MUSIC;
+ mStreamType = AUDIO_STREAM_MUSIC;
mCurrentPosition = -1;
mSeekPosition = -1;
mCurrentState = MEDIA_PLAYER_IDLE;
@@ -551,7 +553,29 @@ status_t MediaPlayer::attachAuxEffect(int effectId)
return mPlayer->attachAuxEffect(effectId);
}
-void MediaPlayer::notify(int msg, int ext1, int ext2)
+status_t MediaPlayer::setParameter(int key, const Parcel& request)
+{
+ LOGV("MediaPlayer::setParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->setParameter(key, request);
+ }
+ LOGV("setParameter: no active player");
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getParameter(int key, Parcel *reply)
+{
+ LOGV("MediaPlayer::getParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->getParameter(key, reply);
+ }
+ LOGV("getParameter: no active player");
+ return INVALID_OPERATION;
+}
+
+void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
bool send = true;
@@ -641,6 +665,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2)
mVideoWidth = ext1;
mVideoHeight = ext2;
break;
+ case MEDIA_TIMED_TEXT:
+ LOGV("Received timed text message");
+ break;
default:
LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
break;
@@ -653,7 +680,7 @@ void MediaPlayer::notify(int msg, int ext1, int ext2)
if ((listener != 0) && send) {
Mutex::Autolock _l(mNotifyLock);
LOGV("callback application");
- listener->notify(msg, ext1, ext2);
+ listener->notify(msg, ext1, ext2, obj);
LOGV("back from callback");
}
}
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index e65f6d8..fadad28 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -31,8 +31,7 @@ LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libstagefright \
libstagefright_omx \
- libstagefright_foundation \
- libsurfaceflinger_client \
+ libstagefright_foundation \
libgui
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 0156634..3b2cf10 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -51,6 +51,9 @@
#include <media/MediaMetadataRetrieverInterface.h>
#include <media/Metadata.h>
#include <media/AudioTrack.h>
+#include <media/MemoryLeakTrackUtil.h>
+
+#include <hardware/audio.h>
#include <private/android_filesystem_config.h>
@@ -392,139 +395,6 @@ static int myTid() {
#endif
}
-#if defined(__arm__)
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
- size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
-// Use the String-class below instead of String8 to allocate all memory
-// beforehand and not reenter the heap while we are examining it...
-struct MyString8 {
- static const size_t MAX_SIZE = 256 * 1024;
-
- MyString8()
- : mPtr((char *)malloc(MAX_SIZE)) {
- *mPtr = '\0';
- }
-
- ~MyString8() {
- free(mPtr);
- }
-
- void append(const char *s) {
- strcat(mPtr, s);
- }
-
- const char *string() const {
- return mPtr;
- }
-
- size_t size() const {
- return strlen(mPtr);
- }
-
-private:
- char *mPtr;
-
- MyString8(const MyString8 &);
- MyString8 &operator=(const MyString8 &);
-};
-
-void memStatus(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- MyString8 result;
-
- typedef struct {
- size_t size;
- size_t dups;
- intptr_t * backtrace;
- } AllocEntry;
-
- uint8_t *info = NULL;
- size_t overallSize = 0;
- size_t infoSize = 0;
- size_t totalMemory = 0;
- size_t backtraceSize = 0;
-
- get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
- if (info) {
- uint8_t *ptr = info;
- size_t count = overallSize / infoSize;
-
- snprintf(buffer, SIZE, " Allocation count %i\n", count);
- result.append(buffer);
- snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
- result.append(buffer);
-
- AllocEntry * entries = new AllocEntry[count];
-
- for (size_t i = 0; i < count; i++) {
- // Each entry should be size_t, size_t, intptr_t[backtraceSize]
- AllocEntry *e = &entries[i];
-
- e->size = *reinterpret_cast<size_t *>(ptr);
- ptr += sizeof(size_t);
-
- e->dups = *reinterpret_cast<size_t *>(ptr);
- ptr += sizeof(size_t);
-
- e->backtrace = reinterpret_cast<intptr_t *>(ptr);
- ptr += sizeof(intptr_t) * backtraceSize;
- }
-
- // Now we need to sort the entries. They come sorted by size but
- // not by stack trace which causes problems using diff.
- bool moved;
- do {
- moved = false;
- for (size_t i = 0; i < (count - 1); i++) {
- AllocEntry *e1 = &entries[i];
- AllocEntry *e2 = &entries[i+1];
-
- bool swap = e1->size < e2->size;
- if (e1->size == e2->size) {
- for(size_t j = 0; j < backtraceSize; j++) {
- if (e1->backtrace[j] == e2->backtrace[j]) {
- continue;
- }
- swap = e1->backtrace[j] < e2->backtrace[j];
- break;
- }
- }
- if (swap) {
- AllocEntry t = entries[i];
- entries[i] = entries[i+1];
- entries[i+1] = t;
- moved = true;
- }
- }
- } while (moved);
-
- for (size_t i = 0; i < count; i++) {
- AllocEntry *e = &entries[i];
-
- snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
- result.append(buffer);
- for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
- if (ct) {
- result.append(", ");
- }
- snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
- result.append(buffer);
- }
- result.append("\n");
- }
-
- delete[] entries;
- free_malloc_leak_info(info);
- }
-
- write(fd, result.string(), result.size());
-}
-#endif
-
status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -623,7 +493,6 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
result.append("\n");
}
-#if defined(__arm__)
bool dumpMem = false;
for (size_t i = 0; i < args.size(); i++) {
if (args[i] == String16("-m")) {
@@ -631,9 +500,8 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
}
}
if (dumpMem) {
- memStatus(fd, args);
+ dumpMemoryAddresses(fd);
}
-#endif
}
write(fd, result.string(), result.size());
return NO_ERROR;
@@ -1156,7 +1024,22 @@ status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
return NO_ERROR;
}
-void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
+status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
+ LOGV("[%d] setParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->setParameter(key, request);
+}
+
+status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
+ LOGV("[%d] getParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->getParameter(key, reply);
+}
+
+void MediaPlayerService::Client::notify(
+ void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
{
Client* client = static_cast<Client*>(cookie);
@@ -1173,7 +1056,7 @@ void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext
client->addNewMetadataUpdate(metadata_type);
}
LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
- client->mClient->notify(msg, ext1, ext2);
+ client->mClient->notify(msg, ext1, ext2, obj);
}
@@ -1342,7 +1225,7 @@ MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
mSessionId(sessionId) {
LOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
- mStreamType = AudioSystem::MUSIC;
+ mStreamType = AUDIO_STREAM_MUSIC;
mLeftVolume = 1.0;
mRightVolume = 1.0;
mLatency = 0;
@@ -1452,7 +1335,7 @@ status_t MediaPlayerService::AudioOutput::open(
mStreamType,
sampleRate,
format,
- (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+ (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
frameCount,
0 /* flags */,
CallbackWrapper,
@@ -1464,7 +1347,7 @@ status_t MediaPlayerService::AudioOutput::open(
mStreamType,
sampleRate,
format,
- (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
+ (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
frameCount,
0,
NULL,
@@ -1583,8 +1466,15 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
size_t actualSize = (*me->mCallback)(
me, buffer->raw, buffer->size, me->mCallbackCookie);
- buffer->size = actualSize;
+ if (actualSize == 0 && buffer->size > 0) {
+ // We've reached EOS but the audio track is not stopped yet,
+ // keep playing silence.
+ memset(buffer->raw, 0, buffer->size);
+ actualSize = buffer->size;
+ }
+
+ buffer->size = actualSize;
}
int MediaPlayerService::AudioOutput::getSessionId()
@@ -1750,7 +1640,8 @@ status_t MediaPlayerService::AudioCache::wait()
return mError;
}
-void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2)
+void MediaPlayerService::AudioCache::notify(
+ void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
{
LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
AudioCache* p = static_cast<AudioCache*>(cookie);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index ff6ccf5..6c4071f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -30,6 +30,8 @@
#include <media/MediaPlayerInterface.h>
#include <media/Metadata.h>
+#include <hardware/audio.h>
+
namespace android {
class IMediaRecorder;
@@ -130,7 +132,7 @@ class MediaPlayerService : public BnMediaPlayerService
virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; }
virtual ssize_t frameCount() const { return mFrameCount; }
virtual ssize_t channelCount() const { return (ssize_t)mChannelCount; }
- virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
+ virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AUDIO_FORMAT_PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
virtual status_t getPosition(uint32_t *position);
@@ -156,7 +158,8 @@ class MediaPlayerService : public BnMediaPlayerService
sp<IMemoryHeap> getHeap() const { return mHeap; }
- static void notify(void* cookie, int msg, int ext1, int ext2);
+ static void notify(void* cookie, int msg,
+ int ext1, int ext2, const Parcel *obj);
virtual status_t dump(int fd, const Vector<String16>& args) const;
private:
@@ -276,6 +279,8 @@ private:
Parcel *reply);
virtual status_t setAuxEffectSendLevel(float level);
virtual status_t attachAuxEffect(int effectId);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
sp<MediaPlayerBase> createPlayer(player_type playerType);
@@ -287,7 +292,8 @@ private:
status_t setDataSource(const sp<IStreamSource> &source);
- static void notify(void* cookie, int msg, int ext1, int ext2);
+ static void notify(void* cookie, int msg,
+ int ext1, int ext2, const Parcel *obj);
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args) const;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 1a1780c..5a47384 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -35,6 +35,8 @@
#include <media/AudioTrack.h>
+#include <hardware/audio.h>
+
#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
@@ -102,7 +104,7 @@ status_t MediaRecorderClient::setAudioSource(int as)
LOGE("recorder is not initialized");
return NO_INIT;
}
- return mRecorder->setAudioSource((audio_source)as);
+ return mRecorder->setAudioSource((audio_source_t)as);
}
status_t MediaRecorderClient::setOutputFormat(int of)
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 5fcf2a7..8f776b4 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -120,7 +120,8 @@ static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
return p;
}
-status_t MetadataRetrieverClient::setDataSource(const char *url)
+status_t MetadataRetrieverClient::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
{
LOGV("setDataSource(%s)", url);
Mutex::Autolock lock(mLock);
@@ -131,7 +132,7 @@ status_t MetadataRetrieverClient::setDataSource(const char *url)
LOGV("player type = %d", playerType);
sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
if (p == NULL) return NO_INIT;
- status_t ret = p->setDataSource(url);
+ status_t ret = p->setDataSource(url, headers);
if (ret == NO_ERROR) mRetriever = p;
return ret;
}
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index b834715..f08f933 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -41,7 +41,10 @@ public:
// Implements IMediaMetadataRetriever interface
// These methods are called in IMediaMetadataRetriever.cpp?
virtual void disconnect();
- virtual status_t setDataSource(const char *url);
+
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
virtual sp<IMemory> extractAlbumArt();
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 1b0b05f..37a3db3 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -30,6 +30,8 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <hardware/audio.h>
+
#include "MidiFile.h"
#ifdef HAVE_GETTID
@@ -58,7 +60,7 @@ static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
MidiFile::MidiFile() :
mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
- mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false),
+ mStreamType(AUDIO_STREAM_MUSIC), mLoop(false), mExit(false),
mPaused(false), mRender(false), mTid(-1)
{
LOGV("constructor");
@@ -423,7 +425,7 @@ status_t MidiFile::setLooping(int loop)
}
status_t MidiFile::createOutputTrack() {
- if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AudioSystem::PCM_16_BIT, 2) != NO_ERROR) {
+ if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) {
LOGE("mAudioSink open failed");
return ERROR_OPEN_FAILED;
}
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index a98231c..b35696f 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -55,6 +55,13 @@ public:
virtual status_t invoke(const Parcel& request, Parcel *reply) {
return INVALID_OPERATION;
}
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+ }
+
private:
status_t createOutputTrack();
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
index ad95fac..aaf2d18 100644
--- a/media/libmediaplayerservice/MidiMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
@@ -35,7 +35,8 @@ void MidiMetadataRetriever::clearMetadataValues()
mMetadataValues[0][0] = '\0';
}
-status_t MidiMetadataRetriever::setDataSource(const char *url)
+status_t MidiMetadataRetriever::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
{
LOGV("setDataSource: %s", url? url: "NULL pointer");
Mutex::Autolock lock(mLock);
@@ -43,8 +44,7 @@ status_t MidiMetadataRetriever::setDataSource(const char *url)
if (mMidiPlayer == 0) {
mMidiPlayer = new MidiFile();
}
- // TODO: support headers in MetadataRetriever interface!
- return mMidiPlayer->setDataSource(url, NULL /* headers */);
+ return mMidiPlayer->setDataSource(url, headers);
}
status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h
index 73ff347..4cee42d 100644
--- a/media/libmediaplayerservice/MidiMetadataRetriever.h
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.h
@@ -31,7 +31,9 @@ public:
MidiMetadataRetriever() {}
~MidiMetadataRetriever() {}
- virtual status_t setDataSource(const char *url);
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
virtual const char* extractMetadata(int keyCode);
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index c5cbd23..02ec911 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -110,7 +110,7 @@ bool StagefrightPlayer::isPlaying() {
}
status_t StagefrightPlayer::seekTo(int msec) {
- LOGV("seekTo");
+ LOGV("seekTo %.2f secs", msec / 1E3);
status_t err = mPlayer->seekTo((int64_t)msec * 1000);
@@ -177,6 +177,16 @@ void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
mPlayer->setAudioSink(audioSink);
}
+status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
+ LOGV("setParameter");
+ return mPlayer->setParameter(key, request);
+}
+
+status_t StagefrightPlayer::getParameter(int key, Parcel *reply) {
+ LOGV("getParameter");
+ return mPlayer->getParameter(key, reply);
+}
+
status_t StagefrightPlayer::getMetadata(
const media::Metadata::Filter& ids, Parcel *records) {
using media::Metadata;
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index e2796d2..ddd37e4 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -55,6 +55,8 @@ public:
virtual player_type playerType();
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index e3dfabb..01fbea1 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -46,6 +46,8 @@
#include <ctype.h>
#include <unistd.h>
+#include <hardware/audio.h>
+
#include "ARTPWriter.h"
namespace android {
@@ -64,7 +66,7 @@ static void addBatteryData(uint32_t params) {
StagefrightRecorder::StagefrightRecorder()
: mWriter(NULL), mWriterAux(NULL),
mOutputFd(-1), mOutputFdAux(-1),
- mAudioSource(AUDIO_SOURCE_LIST_END),
+ mAudioSource(AUDIO_SOURCE_CNT),
mVideoSource(VIDEO_SOURCE_LIST_END),
mStarted(false) {
@@ -82,10 +84,10 @@ status_t StagefrightRecorder::init() {
return OK;
}
-status_t StagefrightRecorder::setAudioSource(audio_source as) {
+status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
LOGV("setAudioSource: %d", as);
if (as < AUDIO_SOURCE_DEFAULT ||
- as >= AUDIO_SOURCE_LIST_END) {
+ as >= AUDIO_SOURCE_CNT) {
LOGE("Invalid audio source: %d", as);
return BAD_VALUE;
}
@@ -800,7 +802,7 @@ status_t StagefrightRecorder::start() {
mStarted = true;
uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
params |= IMediaPlayerService::kBatteryDataTrackAudio;
}
if (mVideoSource != VIDEO_SOURCE_LIST_END) {
@@ -874,7 +876,7 @@ status_t StagefrightRecorder::startAACRecording() {
mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
- CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
+ CHECK(mAudioSource != AUDIO_SOURCE_CNT);
CHECK(0 == "AACWriter is not implemented yet");
@@ -900,7 +902,7 @@ status_t StagefrightRecorder::startAMRRecording() {
}
}
- if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource >= AUDIO_SOURCE_CNT) {
LOGE("Invalid audio source: %d", mAudioSource);
return BAD_VALUE;
}
@@ -933,9 +935,9 @@ status_t StagefrightRecorder::startAMRRecording() {
status_t StagefrightRecorder::startRTPRecording() {
CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
- if ((mAudioSource != AUDIO_SOURCE_LIST_END
+ if ((mAudioSource != AUDIO_SOURCE_CNT
&& mVideoSource != VIDEO_SOURCE_LIST_END)
- || (mAudioSource == AUDIO_SOURCE_LIST_END
+ || (mAudioSource == AUDIO_SOURCE_CNT
&& mVideoSource == VIDEO_SOURCE_LIST_END)) {
// Must have exactly one source.
return BAD_VALUE;
@@ -947,7 +949,7 @@ status_t StagefrightRecorder::startRTPRecording() {
sp<MediaSource> source;
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
source = createAudioSource();
} else {
@@ -975,7 +977,7 @@ status_t StagefrightRecorder::startMPEG2TSRecording() {
sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
if (mAudioEncoder != AUDIO_ENCODER_AAC) {
return ERROR_UNSUPPORTED;
}
@@ -1383,7 +1385,7 @@ status_t StagefrightRecorder::setupMPEG4Recording(
// Audio source is added at the end if it exists.
// This help make sure that the "recoding" sound is suppressed for
// camcorder applications in the recorded files.
- if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) {
+ if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) {
err = setupAudioEncoder(writer);
if (err != OK) return err;
*totalBitRate += mAudioBitRate;
@@ -1504,7 +1506,7 @@ status_t StagefrightRecorder::pause() {
mStarted = false;
uint32_t params = 0;
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
params |= IMediaPlayerService::kBatteryDataTrackAudio;
}
if (mVideoSource != VIDEO_SOURCE_LIST_END) {
@@ -1555,7 +1557,7 @@ status_t StagefrightRecorder::stop() {
mStarted = false;
uint32_t params = 0;
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
params |= IMediaPlayerService::kBatteryDataTrackAudio;
}
if (mVideoSource != VIDEO_SOURCE_LIST_END) {
@@ -1581,7 +1583,7 @@ status_t StagefrightRecorder::reset() {
stop();
// No audio or video source by default
- mAudioSource = AUDIO_SOURCE_LIST_END;
+ mAudioSource = AUDIO_SOURCE_CNT;
mVideoSource = VIDEO_SOURCE_LIST_END;
// Default parameters
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 2c440c1..3d463ea 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -22,6 +22,8 @@
#include <camera/CameraParameters.h>
#include <utils/String8.h>
+#include <hardware/audio.h>
+
namespace android {
class Camera;
@@ -39,7 +41,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual ~StagefrightRecorder();
virtual status_t init();
- virtual status_t setAudioSource(audio_source as);
+ virtual status_t setAudioSource(audio_source_t as);
virtual status_t setVideoSource(video_source vs);
virtual status_t setOutputFormat(output_format of);
virtual status_t setAudioEncoder(audio_encoder ae);
@@ -69,7 +71,7 @@ private:
sp<MediaWriter> mWriter, mWriterAux;
sp<AudioSource> mAudioSourceNode;
- audio_source mAudioSource;
+ audio_source_t mAudioSource;
video_source mVideoSource;
output_format mOutputFormat;
audio_encoder mAudioEncoder;
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index d9c3db3..802a11b 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -99,6 +99,12 @@ class TestPlayerStub : public MediaPlayerInterface {
virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
return mPlayer->invoke(in, out);
}
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return mPlayer->setParameter(key, request);
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return mPlayer->getParameter(key, reply);
+ }
// @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index d07ea1b..576a850 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -33,11 +33,25 @@
namespace android {
-NuPlayer::HTTPLiveSource::HTTPLiveSource(const char *url, uint32_t flags)
+NuPlayer::HTTPLiveSource::HTTPLiveSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers)
: mURL(url),
- mFlags(flags),
+ mFlags(0),
mEOS(false),
mOffset(0) {
+ if (headers) {
+ mExtraHeaders = *headers;
+
+ ssize_t index =
+ mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
+
+ if (index >= 0) {
+ mFlags |= kFlagIncognito;
+
+ mExtraHeaders.removeItemsAt(index);
+ }
+ }
}
NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
@@ -55,7 +69,8 @@ void NuPlayer::HTTPLiveSource::start() {
mLiveLooper->registerHandler(mLiveSession);
- mLiveSession->connect(mURL.c_str());
+ mLiveSession->connect(
+ mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
mTSParser = new ATSParser;
}
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index a8ce7f4..7a337e9 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -27,11 +27,9 @@ struct ATSParser;
struct LiveSession;
struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
- enum Flags {
- // Don't log any URLs.
- kFlagIncognito = 1,
- };
- HTTPLiveSource(const char *url, uint32_t flags = 0);
+ HTTPLiveSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers);
virtual void start();
@@ -49,7 +47,13 @@ protected:
virtual ~HTTPLiveSource();
private:
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1,
+ };
+
AString mURL;
+ KeyedVector<String8, String8> mExtraHeaders;
uint32_t mFlags;
bool mEOS;
off64_t mOffset;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d439f6e..effa703 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -72,17 +72,7 @@ void NuPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
- uint32_t flags = 0;
-
- if (headers) {
- ssize_t index = headers->indexOfKey(String8("x-hide-urls-from-log"));
-
- if (index >= 0) {
- flags |= HTTPLiveSource::kFlagIncognito;
- }
- }
-
- msg->setObject("source", new HTTPLiveSource(url, flags));
+ msg->setObject("source", new HTTPLiveSource(url, headers));
msg->post();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 0eca958..e1213f4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -246,6 +246,14 @@ void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
mPlayer->setAudioSink(audioSink);
}
+status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+}
+
+status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+}
+
status_t NuPlayerDriver::getMetadata(
const media::Metadata::Filter& ids, Parcel *records) {
return INVALID_OPERATION;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 67d0f3e..145fd80 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -52,6 +52,8 @@ struct NuPlayerDriver : public MediaPlayerInterface {
virtual player_type playerType();
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 369a3a8..828e008 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -198,18 +198,21 @@ void NuPlayer::Renderer::signalAudioSinkChanged() {
}
void NuPlayer::Renderer::onDrainAudioQueue() {
- uint32_t numFramesPlayed;
- CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
- ssize_t numFramesAvailableToWrite =
- mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
+ for (;;) {
+ uint32_t numFramesPlayed;
+ CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
- CHECK_GE(numFramesAvailableToWrite, 0);
+ ssize_t numFramesAvailableToWrite =
+ mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
- size_t numBytesAvailableToWrite =
- numFramesAvailableToWrite * mAudioSink->frameSize();
+ size_t numBytesAvailableToWrite =
+ numFramesAvailableToWrite * mAudioSink->frameSize();
+
+ if (numBytesAvailableToWrite == 0) {
+ break;
+ }
- while (numBytesAvailableToWrite > 0) {
if (mAudioQueue.empty()) {
break;
}
@@ -264,10 +267,10 @@ void NuPlayer::Renderer::onDrainAudioQueue() {
if (entry->mOffset == entry->mBuffer->size()) {
entry->mNotifyConsumed->post();
mAudioQueue.erase(mAudioQueue.begin());
+
entry = NULL;
}
- numBytesAvailableToWrite -= copy;
mNumFramesWritten += copy / mAudioSink->frameSize();
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 9928f44..e52f6d1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -505,7 +505,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
// Dequeue buffers and send them to OMX
for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
- android_native_buffer_t *buf;
+ ANativeWindowBuffer *buf;
err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
if (err != 0) {
LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
@@ -574,7 +574,7 @@ status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
}
ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
- android_native_buffer_t *buf;
+ ANativeWindowBuffer *buf;
CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0);
for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 0db3d1d..b10d52c 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -37,7 +37,7 @@ AMRWriter::AMRWriter(const char *filename)
mPaused(false),
mResumed(false) {
- mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
if (mFd >= 0) {
mInitCheck = OK;
}
@@ -269,7 +269,7 @@ status_t AMRWriter::threadFunc() {
}
if (stoppedPrematurely) {
- notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
}
close(mFd);
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
new file mode 100644
index 0000000..6313ca3
--- /dev/null
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -0,0 +1,922 @@
+/*
+ * Copyright (C) 2011 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 "AVIExtractor"
+#include <utils/Log.h>
+
+#include "include/AVIExtractor.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+struct AVIExtractor::AVISource : public MediaSource {
+ AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+ virtual ~AVISource();
+
+private:
+ sp<AVIExtractor> mExtractor;
+ size_t mTrackIndex;
+ const AVIExtractor::Track &mTrack;
+ MediaBufferGroup *mBufferGroup;
+ size_t mSampleIndex;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AVISource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVISource::AVISource(
+ const sp<AVIExtractor> &extractor, size_t trackIndex)
+ : mExtractor(extractor),
+ mTrackIndex(trackIndex),
+ mTrack(mExtractor->mTracks.itemAt(trackIndex)),
+ mBufferGroup(NULL) {
+}
+
+AVIExtractor::AVISource::~AVISource() {
+ if (mBufferGroup) {
+ stop();
+ }
+}
+
+status_t AVIExtractor::AVISource::start(MetaData *params) {
+ CHECK(!mBufferGroup);
+
+ mBufferGroup = new MediaBufferGroup;
+
+ mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+ mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+ mSampleIndex = 0;
+
+ return OK;
+}
+
+status_t AVIExtractor::AVISource::stop() {
+ CHECK(mBufferGroup);
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+ return OK;
+}
+
+sp<MetaData> AVIExtractor::AVISource::getFormat() {
+ return mTrack.mMeta;
+}
+
+status_t AVIExtractor::AVISource::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ CHECK(mBufferGroup);
+
+ *buffer = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ status_t err =
+ mExtractor->getSampleIndexAtTime(
+ mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
+
+ if (err != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+ }
+
+ int64_t timeUs =
+ (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ status_t err = mExtractor->getSampleInfo(
+ mTrackIndex, mSampleIndex, &offset, &size, &isKey);
+
+ ++mSampleIndex;
+
+ if (err != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ MediaBuffer *out;
+ CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
+
+ ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+ }
+
+ out->set_range(0, size);
+
+ out->meta_data()->setInt64(kKeyTime, timeUs);
+
+ if (isKey) {
+ out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ }
+
+ *buffer = out;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
+ : mDataSource(dataSource) {
+ mInitCheck = parseHeaders();
+
+ if (mInitCheck != OK) {
+ mTracks.clear();
+ }
+}
+
+AVIExtractor::~AVIExtractor() {
+}
+
+size_t AVIExtractor::countTracks() {
+ return mTracks.size();
+}
+
+sp<MediaSource> AVIExtractor::getTrack(size_t index) {
+ return index < mTracks.size() ? new AVISource(this, index) : NULL;
+}
+
+sp<MetaData> AVIExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
+}
+
+sp<MetaData> AVIExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck == OK) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
+ }
+
+ return meta;
+}
+
+status_t AVIExtractor::parseHeaders() {
+ mTracks.clear();
+ mMovieOffset = 0;
+ mFoundIndex = false;
+ mOffsetsAreAbsolute = false;
+
+ ssize_t res = parseChunk(0ll, -1ll);
+
+ if (res < 0) {
+ return (status_t)res;
+ }
+
+ if (mMovieOffset == 0ll || !mFoundIndex) {
+ return ERROR_MALFORMED;
+ }
+
+ return OK;
+}
+
+ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
+ if (size >= 0 && size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t tmp[12];
+ ssize_t n = mDataSource->readAt(offset, tmp, 8);
+
+ if (n < 8) {
+ return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+ }
+
+ uint32_t fourcc = U32_AT(tmp);
+ uint32_t chunkSize = U32LE_AT(&tmp[4]);
+
+ if (size >= 0 && chunkSize + 8 > size) {
+ return ERROR_MALFORMED;
+ }
+
+ static const char kPrefix[] = " ";
+ const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
+
+ if (fourcc == FOURCC('L', 'I', 'S', 'T')
+ || fourcc == FOURCC('R', 'I', 'F', 'F')) {
+ // It's a list of chunks
+
+ if (size >= 0 && size < 12) {
+ return ERROR_MALFORMED;
+ }
+
+ n = mDataSource->readAt(offset + 8, &tmp[8], 4);
+
+ if (n < 4) {
+ return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+ }
+
+ uint32_t subFourcc = U32_AT(&tmp[8]);
+
+ LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
+ prefix,
+ offset,
+ (char)(subFourcc >> 24),
+ (char)((subFourcc >> 16) & 0xff),
+ (char)((subFourcc >> 8) & 0xff),
+ (char)(subFourcc & 0xff),
+ chunkSize - 4);
+
+ if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
+ // We're not going to parse this, but will take note of the
+ // offset.
+
+ mMovieOffset = offset;
+ } else {
+ off64_t subOffset = offset + 12;
+ off64_t subOffsetLimit = subOffset + chunkSize - 4;
+ while (subOffset < subOffsetLimit) {
+ ssize_t res =
+ parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
+
+ if (res < 0) {
+ return res;
+ }
+
+ subOffset += res;
+ }
+ }
+ } else {
+ LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
+ prefix,
+ offset,
+ (char)(fourcc >> 24),
+ (char)((fourcc >> 16) & 0xff),
+ (char)((fourcc >> 8) & 0xff),
+ (char)(fourcc & 0xff));
+
+ status_t err = OK;
+
+ switch (fourcc) {
+ case FOURCC('s', 't', 'r', 'h'):
+ {
+ err = parseStreamHeader(offset + 8, chunkSize);
+ break;
+ }
+
+ case FOURCC('s', 't', 'r', 'f'):
+ {
+ err = parseStreamFormat(offset + 8, chunkSize);
+ break;
+ }
+
+ case FOURCC('i', 'd', 'x', '1'):
+ {
+ err = parseIndex(offset + 8, chunkSize);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (chunkSize & 1) {
+ ++chunkSize;
+ }
+
+ return chunkSize + 8;
+}
+
+static const char *GetMIMETypeForHandler(uint32_t handler) {
+ switch (handler) {
+ // Wow... shamelessly copied from
+ // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
+
+ case FOURCC('3', 'I', 'V', '2'):
+ case FOURCC('3', 'i', 'v', '2'):
+ case FOURCC('B', 'L', 'Z', '0'):
+ case FOURCC('D', 'I', 'G', 'I'):
+ case FOURCC('D', 'I', 'V', '1'):
+ case FOURCC('d', 'i', 'v', '1'):
+ case FOURCC('D', 'I', 'V', 'X'):
+ case FOURCC('d', 'i', 'v', 'x'):
+ case FOURCC('D', 'X', '5', '0'):
+ case FOURCC('d', 'x', '5', '0'):
+ case FOURCC('D', 'X', 'G', 'M'):
+ case FOURCC('E', 'M', '4', 'A'):
+ case FOURCC('E', 'P', 'H', 'V'):
+ case FOURCC('F', 'M', 'P', '4'):
+ case FOURCC('f', 'm', 'p', '4'):
+ case FOURCC('F', 'V', 'F', 'W'):
+ case FOURCC('H', 'D', 'X', '4'):
+ case FOURCC('h', 'd', 'x', '4'):
+ case FOURCC('M', '4', 'C', 'C'):
+ case FOURCC('M', '4', 'S', '2'):
+ case FOURCC('m', '4', 's', '2'):
+ case FOURCC('M', 'P', '4', 'S'):
+ case FOURCC('m', 'p', '4', 's'):
+ case FOURCC('M', 'P', '4', 'V'):
+ case FOURCC('m', 'p', '4', 'v'):
+ case FOURCC('M', 'V', 'X', 'M'):
+ case FOURCC('R', 'M', 'P', '4'):
+ case FOURCC('S', 'E', 'D', 'G'):
+ case FOURCC('S', 'M', 'P', '4'):
+ case FOURCC('U', 'M', 'P', '4'):
+ case FOURCC('W', 'V', '1', 'F'):
+ case FOURCC('X', 'V', 'I', 'D'):
+ case FOURCC('X', 'v', 'i', 'D'):
+ case FOURCC('x', 'v', 'i', 'd'):
+ case FOURCC('X', 'V', 'I', 'X'):
+ return MEDIA_MIMETYPE_VIDEO_MPEG4;
+
+ default:
+ return NULL;
+ }
+}
+
+status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
+ if (size != 56) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mTracks.size() > 99) {
+ return -ERANGE;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ uint32_t type = U32_AT(data);
+ uint32_t handler = U32_AT(&data[4]);
+ uint32_t flags = U32LE_AT(&data[8]);
+
+ sp<MetaData> meta = new MetaData;
+
+ uint32_t rate = U32LE_AT(&data[20]);
+ uint32_t scale = U32LE_AT(&data[24]);
+
+ const char *mime = NULL;
+ Track::Kind kind = Track::OTHER;
+
+ if (type == FOURCC('v', 'i', 'd', 's')) {
+ mime = GetMIMETypeForHandler(handler);
+
+ if (mime && strncasecmp(mime, "video/", 6)) {
+ return ERROR_MALFORMED;
+ }
+
+ kind = Track::VIDEO;
+ } else if (type == FOURCC('a', 'u', 'd', 's')) {
+ if (mime && strncasecmp(mime, "audio/", 6)) {
+ return ERROR_MALFORMED;
+ }
+
+ kind = Track::AUDIO;
+ }
+
+ if (!mime) {
+ mime = "application/octet-stream";
+ }
+
+ meta->setCString(kKeyMIMEType, mime);
+
+ mTracks.push();
+ Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+ track->mMeta = meta;
+ track->mRate = rate;
+ track->mScale = scale;
+ track->mKind = kind;
+ track->mNumSyncSamples = 0;
+ track->mThumbnailSampleSize = 0;
+ track->mThumbnailSampleIndex = -1;
+ track->mMaxSampleSize = 0;
+
+ return OK;
+}
+
+status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
+ if (mTracks.isEmpty()) {
+ return ERROR_MALFORMED;
+ }
+
+ Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+ if (track->mKind == Track::OTHER) {
+ // We don't support this content, but that's not a parsing error.
+ return OK;
+ }
+
+ bool isVideo = (track->mKind == Track::VIDEO);
+
+ if ((isVideo && size < 40) || (!isVideo && size < 18)) {
+ // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
+ return ERROR_MALFORMED;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ if (isVideo) {
+ uint32_t width = U32LE_AT(&data[4]);
+ uint32_t height = U32LE_AT(&data[8]);
+
+ track->mMeta->setInt32(kKeyWidth, width);
+ track->mMeta->setInt32(kKeyHeight, height);
+ } else {
+ uint32_t format = U16LE_AT(data);
+ if (format == 0x55) {
+ track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ }
+
+ uint32_t numChannels = U16LE_AT(&data[2]);
+ uint32_t sampleRate = U32LE_AT(&data[4]);
+
+ track->mMeta->setInt32(kKeyChannelCount, numChannels);
+ track->mMeta->setInt32(kKeySampleRate, sampleRate);
+ }
+
+ return OK;
+}
+
+// static
+bool AVIExtractor::IsCorrectChunkType(
+ ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
+ uint32_t chunkBase = chunkType & 0xffff;
+
+ switch (kind) {
+ case Track::VIDEO:
+ {
+ if (chunkBase != FOURCC(0, 0, 'd', 'c')
+ && chunkBase != FOURCC(0, 0, 'd', 'b')) {
+ return false;
+ }
+ break;
+ }
+
+ case Track::AUDIO:
+ {
+ if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
+ return false;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (trackIndex < 0) {
+ return true;
+ }
+
+ uint8_t hi = chunkType >> 24;
+ uint8_t lo = (chunkType >> 16) & 0xff;
+
+ if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+ return false;
+ }
+
+ if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
+ return false;
+ }
+
+ return true;
+}
+
+status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
+ if ((size % 16) != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ while (size > 0) {
+ uint32_t chunkType = U32_AT(data);
+
+ uint8_t hi = chunkType >> 24;
+ uint8_t lo = (chunkType >> 16) & 0xff;
+
+ if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+ return ERROR_MALFORMED;
+ }
+
+ size_t trackIndex = 10 * (hi - '0') + (lo - '0');
+
+ if (trackIndex >= mTracks.size()) {
+ return ERROR_MALFORMED;
+ }
+
+ Track *track = &mTracks.editItemAt(trackIndex);
+
+ if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (track->mKind == Track::OTHER) {
+ data += 16;
+ size -= 16;
+ continue;
+ }
+
+ uint32_t flags = U32LE_AT(&data[4]);
+ uint32_t offset = U32LE_AT(&data[8]);
+ uint32_t chunkSize = U32LE_AT(&data[12]);
+
+ if (chunkSize > track->mMaxSampleSize) {
+ track->mMaxSampleSize = chunkSize;
+ }
+
+ track->mSamples.push();
+
+ SampleInfo *info =
+ &track->mSamples.editItemAt(track->mSamples.size() - 1);
+
+ info->mOffset = offset;
+ info->mIsKey = (flags & 0x10) != 0;
+
+ if (info->mIsKey) {
+ static const size_t kMaxNumSyncSamplesToScan = 20;
+
+ if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
+ if (chunkSize > track->mThumbnailSampleSize) {
+ track->mThumbnailSampleSize = chunkSize;
+
+ track->mThumbnailSampleIndex =
+ track->mSamples.size() - 1;
+ }
+ }
+
+ ++track->mNumSyncSamples;
+ }
+
+ data += 16;
+ size -= 16;
+ }
+
+ if (!mTracks.isEmpty()) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ status_t err = getSampleInfo(0, 0, &offset, &size, &isKey);
+
+ if (err != OK) {
+ mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
+ err = getSampleInfo(0, 0, &offset, &size, &isKey);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ LOGV("Chunk offsets are %s",
+ mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
+ }
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ Track *track = &mTracks.editItemAt(i);
+
+ int64_t durationUs =
+ (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale;
+
+ LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
+
+ track->mMeta->setInt64(kKeyDuration, durationUs);
+ track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
+
+ const char *tmp;
+ CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
+
+ AString mime = tmp;
+
+ if (!strncasecmp("video/", mime.c_str(), 6)
+ && track->mThumbnailSampleIndex >= 0) {
+ int64_t thumbnailTimeUs =
+ (track->mThumbnailSampleIndex * 1000000ll * track->mRate)
+ / track->mScale;
+
+ track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+
+ if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+ status_t err = addMPEG4CodecSpecificData(i);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+ }
+ }
+
+ mFoundIndex = true;
+
+ return OK;
+}
+
+static size_t GetSizeWidth(size_t x) {
+ size_t n = 1;
+ while (x > 127) {
+ ++n;
+ x >>= 7;
+ }
+ return n;
+}
+
+static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
+ while (x > 127) {
+ *dst++ = (x & 0x7f) | 0x80;
+ x >>= 7;
+ }
+ *dst++ = x;
+ return dst;
+}
+
+sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
+ size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
+ size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
+ size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
+
+ sp<ABuffer> csd = new ABuffer(len3);
+ uint8_t *dst = csd->data();
+ *dst++ = 0x03;
+ dst = EncodeSize(dst, len2 + 3);
+ *dst++ = 0x00; // ES_ID
+ *dst++ = 0x00;
+ *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ *dst++ = 0x04;
+ dst = EncodeSize(dst, len1 + 13);
+ *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile
+ for (size_t i = 0; i < 12; ++i) {
+ *dst++ = 0x00;
+ }
+
+ *dst++ = 0x05;
+ dst = EncodeSize(dst, config->size());
+ memcpy(dst, config->data(), config->size());
+ dst += config->size();
+
+ // hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
+ Track *track = &mTracks.editItemAt(trackIndex);
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey);
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ // Extract everything up to the first VOP start code from the first
+ // frame's encoded data and use it to construct an ESDS with the
+ // codec specific data.
+
+ size_t i = 0;
+ bool found = false;
+ while (i + 3 < buffer->size()) {
+ if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
+ found = true;
+ break;
+ }
+
+ ++i;
+ }
+
+ if (!found) {
+ return ERROR_MALFORMED;
+ }
+
+ buffer->setRange(0, i);
+
+ sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
+ track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
+
+ return OK;
+}
+
+status_t AVIExtractor::getSampleInfo(
+ size_t trackIndex, size_t sampleIndex,
+ off64_t *offset, size_t *size, bool *isKey) {
+ if (trackIndex >= mTracks.size()) {
+ return -ERANGE;
+ }
+
+ const Track &track = mTracks.itemAt(trackIndex);
+
+ if (sampleIndex >= track.mSamples.size()) {
+ return -ERANGE;
+ }
+
+ const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
+
+ if (!mOffsetsAreAbsolute) {
+ *offset = info.mOffset + mMovieOffset + 8;
+ } else {
+ *offset = info.mOffset;
+ }
+
+ *size = 0;
+
+ uint8_t tmp[8];
+ ssize_t n = mDataSource->readAt(*offset, tmp, 8);
+
+ if (n < 8) {
+ return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+ }
+
+ uint32_t chunkType = U32_AT(tmp);
+
+ if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
+ return ERROR_MALFORMED;
+ }
+
+ *offset += 8;
+ *size = U32LE_AT(&tmp[4]);
+
+ *isKey = info.mIsKey;
+
+ return OK;
+}
+
+status_t AVIExtractor::getSampleIndexAtTime(
+ size_t trackIndex,
+ int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+ size_t *sampleIndex) const {
+ if (trackIndex >= mTracks.size()) {
+ return -ERANGE;
+ }
+
+ const Track &track = mTracks.itemAt(trackIndex);
+
+ ssize_t closestSampleIndex =
+ timeUs / track.mRate * track.mScale / 1000000ll;
+
+ ssize_t numSamples = track.mSamples.size();
+
+ if (closestSampleIndex < 0) {
+ closestSampleIndex = 0;
+ } else if (closestSampleIndex >= numSamples) {
+ closestSampleIndex = numSamples - 1;
+ }
+
+ if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
+ *sampleIndex = closestSampleIndex;
+
+ return OK;
+ }
+
+ ssize_t prevSyncSampleIndex = closestSampleIndex;
+ while (prevSyncSampleIndex >= 0) {
+ const SampleInfo &info =
+ track.mSamples.itemAt(prevSyncSampleIndex);
+
+ if (info.mIsKey) {
+ break;
+ }
+
+ --prevSyncSampleIndex;
+ }
+
+ ssize_t nextSyncSampleIndex = closestSampleIndex;
+ while (nextSyncSampleIndex < numSamples) {
+ const SampleInfo &info =
+ track.mSamples.itemAt(nextSyncSampleIndex);
+
+ if (info.mIsKey) {
+ break;
+ }
+
+ ++nextSyncSampleIndex;
+ }
+
+ switch (mode) {
+ case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
+ {
+ *sampleIndex = prevSyncSampleIndex;
+
+ return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
+ }
+
+ case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
+ {
+ *sampleIndex = nextSyncSampleIndex;
+
+ return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
+ }
+
+ case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
+ {
+ if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (prevSyncSampleIndex < 0) {
+ *sampleIndex = nextSyncSampleIndex;
+ return OK;
+ }
+
+ if (nextSyncSampleIndex >= numSamples) {
+ *sampleIndex = prevSyncSampleIndex;
+ return OK;
+ }
+
+ size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
+ size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
+
+ *sampleIndex =
+ (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
+
+ return OK;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+bool SniffAVI(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ char tmp[12];
+ if (source->readAt(0, tmp, 12) < 12) {
+ return false;
+ }
+
+ if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
+ *confidence = 0.2;
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 88069e9..6c7176c 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \
AACExtractor.cpp \
AMRExtractor.cpp \
AMRWriter.cpp \
+ AVIExtractor.cpp \
AudioPlayer.cpp \
AudioSource.cpp \
AwesomePlayer.cpp \
@@ -19,6 +20,7 @@ LOCAL_SRC_FILES:= \
ESDS.cpp \
FileSource.cpp \
FLACExtractor.cpp \
+ HTTPBase.cpp \
HTTPStream.cpp \
JPEGSource.cpp \
MP3Extractor.cpp \
@@ -46,6 +48,7 @@ LOCAL_SRC_FILES:= \
ThrottledSource.cpp \
TimeSource.cpp \
TimedEventQueue.cpp \
+ TimedTextPlayer.cpp \
Utils.cpp \
VBRISeeker.cpp \
WAVExtractor.cpp \
@@ -69,13 +72,12 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libsonivox \
libvorbisidec \
- libsurfaceflinger_client \
libstagefright_yuv \
libcamera_client \
libdrmframework \
libcrypto \
libssl \
- libgui
+ libgui \
LOCAL_STATIC_LIBRARIES := \
libstagefright_color_conversion \
@@ -101,6 +103,60 @@ LOCAL_STATIC_LIBRARIES := \
libstagefright_g711dec \
libFLAC \
+################################################################################
+
+# The following was shamelessly copied from external/webkit/Android.mk and
+# currently must follow the same logic to determine how webkit was built and
+# if it's safe to link against libchromium.net
+
+# V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot
+# use the Chrome http stack either.
+ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
+ USE_ALT_HTTP := true
+endif
+
+# See if the user has specified a stack they want to use
+HTTP_STACK = $(HTTP)
+# We default to the Chrome HTTP stack.
+DEFAULT_HTTP = chrome
+ALT_HTTP = android
+
+ifneq ($(HTTP_STACK),chrome)
+ ifneq ($(HTTP_STACK),android)
+ # No HTTP stack is specified, pickup the one we want as default.
+ ifeq ($(USE_ALT_HTTP),true)
+ HTTP_STACK = $(ALT_HTTP)
+ else
+ HTTP_STACK = $(DEFAULT_HTTP)
+ endif
+ endif
+endif
+
+ifeq ($(HTTP_STACK),chrome)
+
+LOCAL_SHARED_LIBRARIES += \
+ liblog \
+ libicuuc \
+ libicui18n \
+ libz \
+ libdl \
+
+LOCAL_STATIC_LIBRARIES += \
+ libstagefright_chromium_http \
+ libchromium_net \
+ libwebcore \
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
+
+endif # ifeq ($(HTTP_STACK),chrome)
+
+################################################################################
+
LOCAL_SHARED_LIBRARIES += \
libstagefright_amrnb_common \
libstagefright_enc_common \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index bd04a26..69f9c23 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -110,7 +110,7 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
if (mAudioSink.get() != NULL) {
status_t err = mAudioSink->open(
- mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
+ mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback, this);
if (err != OK) {
@@ -132,10 +132,10 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
mAudioSink->start();
} else {
mAudioTrack = new AudioTrack(
- AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
+ AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
(numChannels == 2)
- ? AudioSystem::CHANNEL_OUT_STEREO
- : AudioSystem::CHANNEL_OUT_MONO,
+ ? AUDIO_CHANNEL_OUT_STEREO
+ : AUDIO_CHANNEL_OUT_MONO,
0, 0, &AudioCallback, this, 0);
if ((err = mAudioTrack->initCheck()) != OK) {
@@ -280,17 +280,39 @@ void AudioPlayer::AudioCallback(int event, void *info) {
buffer->size = numBytesWritten;
}
+uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
+ uint32_t numFramesPlayedOut;
+ status_t err;
+
+ if (mAudioSink != NULL) {
+ err = mAudioSink->getPosition(&numFramesPlayedOut);
+ } else {
+ err = mAudioTrack->getPosition(&numFramesPlayedOut);
+ }
+
+ if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
+ return 0;
+ }
+
+ // mNumFramesPlayed is the number of frames submitted
+ // to the audio sink for playback, but not all of them
+ // may have played out by now.
+ return mNumFramesPlayed - numFramesPlayedOut;
+}
+
size_t AudioPlayer::fillBuffer(void *data, size_t size) {
if (mNumFramesPlayed == 0) {
LOGV("AudioCallback");
}
if (mReachedEOS) {
- memset(data, 0, size);
-
- return size;
+ return 0;
}
+ bool postSeekComplete = false;
+ bool postEOS = false;
+ int64_t postEOSDelayUs = 0;
+
size_t size_done = 0;
size_t size_remaining = size;
while (size_remaining > 0) {
@@ -317,7 +339,7 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
mSeeking = false;
if (mObserver) {
- mObserver->postAudioSeekComplete();
+ postSeekComplete = true;
}
}
}
@@ -342,7 +364,35 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
if (err != OK) {
if (mObserver && !mReachedEOS) {
- mObserver->postAudioEOS();
+ // We don't want to post EOS right away but only
+ // after all frames have actually been played out.
+
+ // These are the number of frames submitted to the
+ // AudioTrack that you haven't heard yet.
+ uint32_t numFramesPendingPlayout =
+ getNumFramesPendingPlayout();
+
+ // These are the number of frames we're going to
+ // submit to the AudioTrack by returning from this
+ // callback.
+ uint32_t numAdditionalFrames = size_done / mFrameSize;
+
+ numFramesPendingPlayout += numAdditionalFrames;
+
+ int64_t timeToCompletionUs =
+ (1000000ll * numFramesPendingPlayout) / mSampleRate;
+
+ LOGV("total number of frames played: %lld (%lld us)",
+ (mNumFramesPlayed + numAdditionalFrames),
+ 1000000ll * (mNumFramesPlayed + numAdditionalFrames)
+ / mSampleRate);
+
+ LOGV("%d frames left to play, %lld us (%.2f secs)",
+ numFramesPendingPlayout,
+ timeToCompletionUs, timeToCompletionUs / 1E6);
+
+ postEOS = true;
+ postEOSDelayUs = timeToCompletionUs + mLatencyUs;
}
mReachedEOS = true;
@@ -386,8 +436,18 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
size_remaining -= copy;
}
- Mutex::Autolock autoLock(mLock);
- mNumFramesPlayed += size_done / mFrameSize;
+ {
+ Mutex::Autolock autoLock(mLock);
+ mNumFramesPlayed += size_done / mFrameSize;
+ }
+
+ if (postEOS) {
+ mObserver->postAudioEOS(postEOSDelayUs);
+ }
+
+ if (postSeekComplete) {
+ mObserver->postAudioSeekComplete();
+ }
return size_done;
}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index bbdec02..99c3682 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -60,8 +60,8 @@ AudioSource::AudioSource(
AudioRecord::RECORD_NS_ENABLE |
AudioRecord::RECORD_IIR_ENABLE;
mRecord = new AudioRecord(
- inputSource, sampleRate, AudioSystem::PCM_16_BIT,
- channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
+ inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
+ channels > 1? AUDIO_CHANNEL_IN_STEREO: AUDIO_CHANNEL_IN_MONO,
4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
flags,
AudioRecordCallbackFunction,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 027a1ce..cccd0b7 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -28,6 +28,7 @@
#include "include/NuCachedSource2.h"
#include "include/ThrottledSource.h"
#include "include/MPEG2TSExtractor.h"
+#include "include/TimedTextPlayer.h"
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -55,7 +56,6 @@
#include <cutils/properties.h>
#define USE_SURFACE_ALLOC 1
-#define FRAME_DROP_FREQ 0
namespace android {
@@ -185,7 +185,9 @@ AwesomePlayer::AwesomePlayer()
mFlags(0),
mExtractorFlags(0),
mVideoBuffer(NULL),
- mDecryptHandle(NULL) {
+ mDecryptHandle(NULL),
+ mLastVideoTimeUs(-1),
+ mTextPlayer(NULL) {
CHECK_EQ(mClient.connect(), (status_t)OK);
DataSource::RegisterDefaultSniffers();
@@ -308,11 +310,11 @@ status_t AwesomePlayer::setDataSource_l(
return UNKNOWN_ERROR;
}
- dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+ dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
if (mDecryptHandle != NULL) {
CHECK(mDrmManagerClient);
if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
- notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
}
}
@@ -381,10 +383,8 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
mFlags |= AUTO_LOOPING;
}
}
- }
-
- if (haveAudio && haveVideo) {
- break;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ addTextSource(extractor->getTrack(i));
}
}
@@ -469,30 +469,20 @@ void AwesomePlayer::reset_l() {
delete mAudioPlayer;
mAudioPlayer = NULL;
- mVideoRenderer.clear();
-
- if (mVideoBuffer) {
- mVideoBuffer->release();
- mVideoBuffer = NULL;
+ if (mTextPlayer != NULL) {
+ delete mTextPlayer;
+ mTextPlayer = NULL;
}
+ mVideoRenderer.clear();
+
if (mRTSPController != NULL) {
mRTSPController->disconnect();
mRTSPController.clear();
}
if (mVideoSource != NULL) {
- mVideoSource->stop();
-
- // The following hack is necessary to ensure that the OMX
- // component is completely released by the time we may try
- // to instantiate it again.
- wp<MediaSource> tmp = mVideoSource;
- mVideoSource.clear();
- while (tmp.promote() != NULL) {
- usleep(1000);
- }
- IPCThreadState::self()->flushCommands();
+ shutdownVideoDecoder_l();
}
mDurationUs = -1;
@@ -511,6 +501,7 @@ void AwesomePlayer::reset_l() {
mFileSource.clear();
mBitrate = -1;
+ mLastVideoTimeUs = -1;
}
void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -880,6 +871,17 @@ void AwesomePlayer::notifyVideoSize_l() {
cropLeft, cropTop, cropRight, cropBottom);
}
+ int32_t displayWidth;
+ if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+ LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
+ mDisplayWidth = displayWidth;
+ }
+ int32_t displayHeight;
+ if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+ LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
+ mDisplayHeight = displayHeight;
+ }
+
int32_t usableWidth = cropRight - cropLeft + 1;
int32_t usableHeight = cropBottom - cropTop + 1;
if (mDisplayWidth != 0) {
@@ -974,6 +976,11 @@ status_t AwesomePlayer::pause_l(bool at_eos) {
mFlags &= ~AUDIO_RUNNING;
}
+ if (mFlags & TEXTPLAYER_STARTED) {
+ mTextPlayer->pause();
+ mFlags &= ~TEXT_RUNNING;
+ }
+
mFlags &= ~PLAYING;
if (mDecryptHandle != NULL) {
@@ -1002,7 +1009,7 @@ void AwesomePlayer::setSurface(const sp<Surface> &surface) {
Mutex::Autolock autoLock(mLock);
mSurface = surface;
- mNativeWindow = surface;
+ setNativeWindow_l(surface);
}
void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
@@ -1010,9 +1017,57 @@ void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture)
mSurface.clear();
if (surfaceTexture != NULL) {
- mNativeWindow = new SurfaceTextureClient(surfaceTexture);
+ setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
+ }
+}
+
+void AwesomePlayer::shutdownVideoDecoder_l() {
+ if (mVideoBuffer) {
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+ }
+
+ mVideoSource->stop();
+
+ // The following hack is necessary to ensure that the OMX
+ // component is completely released by the time we may try
+ // to instantiate it again.
+ wp<MediaSource> tmp = mVideoSource;
+ mVideoSource.clear();
+ while (tmp.promote() != NULL) {
+ usleep(1000);
+ }
+ IPCThreadState::self()->flushCommands();
+}
+
+void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
+ mNativeWindow = native;
+
+ if (mVideoSource == NULL) {
+ return;
}
+ LOGI("attempting to reconfigure to use new surface");
+
+ bool wasPlaying = (mFlags & PLAYING) != 0;
+
+ pause_l();
+ mVideoRenderer.clear();
+
+ shutdownVideoDecoder_l();
+
+ CHECK_EQ(initVideoDecoder(), (status_t)OK);
+
+ if (mLastVideoTimeUs >= 0) {
+ mSeeking = SEEK;
+ mSeekNotificationSent = true;
+ mSeekTimeUs = mLastVideoTimeUs;
+ mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
+ }
+
+ if (wasPlaying) {
+ play_l();
+ }
}
void AwesomePlayer::setAudioSink(
@@ -1074,6 +1129,32 @@ status_t AwesomePlayer::seekTo(int64_t timeUs) {
return OK;
}
+status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
+ if (mTextPlayer != NULL) {
+ if (index >= 0) { // to turn on a text track
+ status_t err = mTextPlayer->setTimedTextTrackIndex(index);
+ if (err != OK) {
+ return err;
+ }
+
+ mFlags |= TEXT_RUNNING;
+ mFlags |= TEXTPLAYER_STARTED;
+ return OK;
+ } else { // to turn off the text track display
+ if (mFlags & TEXT_RUNNING) {
+ mFlags &= ~TEXT_RUNNING;
+ }
+ if (mFlags & TEXTPLAYER_STARTED) {
+ mFlags &= ~TEXTPLAYER_STARTED;
+ }
+
+ return mTextPlayer->setTimedTextTrackIndex(index);
+ }
+ } else {
+ return INVALID_OPERATION;
+ }
+}
+
// static
void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
@@ -1110,6 +1191,10 @@ status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
seekAudioIfNecessary_l();
+ if (mFlags & TEXTPLAYER_STARTED) {
+ mTextPlayer->seekTo(mSeekTimeUs);
+ }
+
if (!(mFlags & PLAYING)) {
LOGV("seeking while paused, sending SEEK_COMPLETE notification"
" immediately.");
@@ -1132,7 +1217,6 @@ void AwesomePlayer::seekAudioIfNecessary_l() {
mWatchForAudioSeekComplete = true;
mWatchForAudioEOS = true;
- mSeekNotificationSent = false;
if (mDecryptHandle != NULL) {
mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
@@ -1149,6 +1233,16 @@ void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
mAudioTrack = source;
}
+void AwesomePlayer::addTextSource(sp<MediaSource> source) {
+ CHECK(source != NULL);
+
+ if (mTextPlayer == NULL) {
+ mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
+ }
+
+ mTextPlayer->addTextSource(source);
+}
+
status_t AwesomePlayer::initAudioDecoder() {
sp<MetaData> meta = mAudioTrack->getFormat();
@@ -1291,11 +1385,11 @@ void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
// If we're playing video only, report seek complete now,
// otherwise audio player will notify us later.
notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
}
mFlags |= FIRST_FRAME;
mSeeking = NO_SEEK;
- mSeekNotificationSent = false;
if (mDecryptHandle != NULL) {
mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
@@ -1403,6 +1497,8 @@ void AwesomePlayer::onVideoEvent() {
int64_t timeUs;
CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ mLastVideoTimeUs = timeUs;
+
if (mSeeking == SEEK_VIDEO_ONLY) {
if (mSeekTimeUs > timeUs) {
LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
@@ -1426,11 +1522,15 @@ void AwesomePlayer::onVideoEvent() {
}
}
+ if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
+ mTextPlayer->resume();
+ mFlags |= TEXT_RUNNING;
+ }
+
TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
if (mFlags & FIRST_FRAME) {
mFlags &= ~FIRST_FRAME;
- mSinceLastDropped = 0;
mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
}
@@ -1477,17 +1577,13 @@ void AwesomePlayer::onVideoEvent() {
if (latenessUs > 40000) {
// We're more than 40ms late.
- LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
- if ( mSinceLastDropped > FRAME_DROP_FREQ)
- {
- LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
- mSinceLastDropped = 0;
- mVideoBuffer->release();
- mVideoBuffer = NULL;
+ LOGV("we're late by %lld us (%.2f secs), dropping frame",
+ latenessUs, latenessUs / 1E6);
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
- postVideoEvent_l();
- return;
- }
+ postVideoEvent_l();
+ return;
}
if (latenessUs < -10000) {
@@ -1505,7 +1601,6 @@ void AwesomePlayer::onVideoEvent() {
}
if (mVideoRenderer != NULL) {
- mSinceLastDropped++;
mVideoRenderer->render(mVideoBuffer);
}
@@ -1555,12 +1650,12 @@ void AwesomePlayer::postVideoLagEvent_l() {
mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
}
-void AwesomePlayer::postCheckAudioStatusEvent_l() {
+void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
if (mAudioStatusEventPending) {
return;
}
mAudioStatusEventPending = true;
- mQueue.postEvent(mCheckAudioStatusEvent);
+ mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
}
void AwesomePlayer::onCheckAudioStatus() {
@@ -1656,8 +1751,10 @@ status_t AwesomePlayer::finishSetDataSource_l() {
if (!strncasecmp("http://", mUri.string(), 7)
|| !strncasecmp("https://", mUri.string(), 8)) {
- mConnectingDataSource = new NuHTTPDataSource(
- (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
+ mConnectingDataSource = HTTPBase::Create(
+ (mFlags & INCOGNITO)
+ ? HTTPBase::kFlagIncognito
+ : 0);
mLock.unlock();
status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
@@ -1681,29 +1778,37 @@ status_t AwesomePlayer::finishSetDataSource_l() {
dataSource = mCachedSource;
- // We're going to prefill the cache before trying to instantiate
- // the extractor below, as the latter is an operation that otherwise
- // could block on the datasource for a significant amount of time.
- // During that time we'd be unable to abort the preparation phase
- // without this prefill.
+ String8 contentType = dataSource->getMIMEType();
- mLock.unlock();
+ if (strncasecmp(contentType.string(), "audio/", 6)) {
+ // We're not doing this for streams that appear to be audio-only
+ // streams to ensure that even low bandwidth streams start
+ // playing back fairly instantly.
- for (;;) {
- status_t finalStatus;
- size_t cachedDataRemaining =
- mCachedSource->approxDataRemaining(&finalStatus);
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ mLock.unlock();
+
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+ || (mFlags & PREPARE_CANCELLED)) {
+ break;
+ }
- if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
- || (mFlags & PREPARE_CANCELLED)) {
- break;
+ usleep(200000);
}
- usleep(200000);
+ mLock.lock();
}
- mLock.lock();
-
if (mFlags & PREPARE_CANCELLED) {
LOGI("Prepare cancelled while waiting for initial cache fill.");
return UNKNOWN_ERROR;
@@ -1746,11 +1851,12 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return UNKNOWN_ERROR;
}
- dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+ dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+
if (mDecryptHandle != NULL) {
CHECK(mDrmManagerClient);
if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
- notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
}
}
@@ -1844,12 +1950,24 @@ uint32_t AwesomePlayer::flags() const {
return mExtractorFlags;
}
-void AwesomePlayer::postAudioEOS() {
- postCheckAudioStatusEvent_l();
+void AwesomePlayer::postAudioEOS(int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+ postCheckAudioStatusEvent_l(delayUs);
}
void AwesomePlayer::postAudioSeekComplete() {
- postCheckAudioStatusEvent_l();
+ Mutex::Autolock autoLock(mLock);
+ postCheckAudioStatusEvent_l(0 /* delayUs */);
}
+status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
+ if (key == KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX) {
+ return setTimedTextTrackIndex(request.readInt32());
+ }
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
+ return OK;
+}
} // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 8a24bc4..a1f04d3 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -740,28 +740,6 @@ void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
mFrameAvailableCondition.signal();
}
-size_t CameraSource::getNumberOfVideoBuffers() const {
- LOGV("getNumberOfVideoBuffers");
- size_t nBuffers = 0;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if (mInitCheck == OK && mCamera != 0) {
- nBuffers = mCamera->getNumberOfVideoBuffers();
- }
- IPCThreadState::self()->restoreCallingIdentity(token);
- return nBuffers;
-}
-
-sp<IMemory> CameraSource::getVideoBuffer(size_t index) const {
- LOGV("getVideoBuffer: %d", index);
- sp<IMemory> buffer = 0;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if (mInitCheck == OK && mCamera != 0) {
- buffer = mCamera->getVideoBuffer(index);
- }
- IPCThreadState::self()->restoreCallingIdentity(token);
- return buffer;
-}
-
bool CameraSource::isMetaDataStoredInVideoBuffers() const {
LOGV("isMetaDataStoredInVideoBuffers");
return mIsMetaDataStoredInVideoBuffers;
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 2809df5..1f3d581 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -41,7 +41,7 @@ namespace android {
class DRMSource : public MediaSource {
public:
DRMSource(const sp<MediaSource> &mediaSource,
- DecryptHandle *decryptHandle,
+ const sp<DecryptHandle> &decryptHandle,
DrmManagerClient *managerClient,
int32_t trackId, DrmBuffer *ipmpBox);
@@ -56,7 +56,7 @@ protected:
private:
sp<MediaSource> mOriginalMediaSource;
- DecryptHandle* mDecryptHandle;
+ sp<DecryptHandle> mDecryptHandle;
DrmManagerClient* mDrmManagerClient;
size_t mTrackId;
mutable Mutex mDRMLock;
@@ -70,7 +70,7 @@ private:
////////////////////////////////////////////////////////////////////////////////
DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
- DecryptHandle *decryptHandle,
+ const sp<DecryptHandle> &decryptHandle,
DrmManagerClient *managerClient,
int32_t trackId, DrmBuffer *ipmpBox)
: mOriginalMediaSource(mediaSource),
@@ -146,18 +146,14 @@ status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
- &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != DRM_NO_ERROR) {
+ &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
if (decryptedDrmBuffer.data) {
delete [] decryptedDrmBuffer.data;
decryptedDrmBuffer.data = NULL;
}
- if (err == DRM_ERROR_LICENSE_EXPIRED) {
- return ERROR_NO_LICENSE;
- } else {
- return ERROR_IO;
- }
+ return err;
}
CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);
@@ -245,7 +241,7 @@ DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
mOriginalExtractor->setDrmFlag(true);
mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
- source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+ source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
}
DRMExtractor::~DRMExtractor() {
@@ -281,7 +277,7 @@ sp<MetaData> DRMExtractor::getMetaData() {
bool SniffDRM(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
- DecryptHandle *decryptHandle = source->DrmInitialization();
+ sp<DecryptHandle> decryptHandle = source->DrmInitialization();
if (decryptHandle != NULL) {
if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 3b38208..c16b3b5 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -15,13 +15,14 @@
*/
#include "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
#include "include/MP3Extractor.h"
#include "include/MPEG4Extractor.h"
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
#include "include/MPEG2TSExtractor.h"
#include "include/NuCachedSource2.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
#include "include/DRMExtractor.h"
#include "include/FLACExtractor.h"
#include "include/AACExtractor.h"
@@ -111,6 +112,7 @@ void DataSource::RegisterDefaultSniffers() {
RegisterSniffer(SniffMPEG2TS);
RegisterSniffer(SniffMP3);
RegisterSniffer(SniffAAC);
+ RegisterSniffer(SniffAVI);
char value[PROPERTY_VALUE_MAX];
if (property_get("drm.service.enabled", value, NULL)
@@ -127,7 +129,7 @@ sp<DataSource> DataSource::CreateFromURI(
source = new FileSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)
|| !strncasecmp("https://", uri, 8)) {
- sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource;
+ sp<HTTPBase> httpSource = HTTPBase::Create();
if (httpSource->connect(uri, headers) != OK) {
return NULL;
}
@@ -144,4 +146,8 @@ sp<DataSource> DataSource::CreateFromURI(
return source;
}
+String8 DataSource::getMIMEType() const {
+ return String8("application/octet-stream");
+}
+
} // namespace android
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 02a78c9..f2f3500 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -125,7 +125,7 @@ status_t FileSource::getSize(off64_t *size) {
return OK;
}
-DecryptHandle* FileSource::DrmInitialization() {
+sp<DecryptHandle> FileSource::DrmInitialization() {
if (mDrmManagerClient == NULL) {
mDrmManagerClient = new DrmManagerClient();
}
@@ -147,8 +147,8 @@ DecryptHandle* FileSource::DrmInitialization() {
return mDecryptHandle;
}
-void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
- *handle = mDecryptHandle;
+void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ handle = mDecryptHandle;
*client = mDrmManagerClient;
}
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
new file mode 100644
index 0000000..58b17a7
--- /dev/null
+++ b/media/libstagefright/HTTPBase.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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 "include/HTTPBase.h"
+
+#if CHROMIUM_AVAILABLE
+#include "include/ChromiumHTTPDataSource.h"
+#endif
+
+#include "include/NuHTTPDataSource.h"
+
+#include <cutils/properties.h>
+
+namespace android {
+
+HTTPBase::HTTPBase() {}
+
+// static
+sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
+#if CHROMIUM_AVAILABLE
+ char value[PROPERTY_VALUE_MAX];
+ if (!property_get("media.stagefright.use-chromium", value, NULL)
+ || (strcasecmp("false", value) && strcmp("0", value))) {
+ return new ChromiumHTTPDataSource(flags);
+ } else
+#endif
+ {
+ return new NuHTTPDataSource(flags);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 03ce202..4bdfc6f 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -48,7 +48,7 @@ static const uint32_t kMask = 0xfffe0c00;
bool MP3Extractor::get_mp3_frame_size(
uint32_t header, size_t *frame_size,
int *out_sampling_rate, int *out_channels,
- int *out_bitrate) {
+ int *out_bitrate, int *out_num_samples) {
*frame_size = 0;
if (out_sampling_rate) {
@@ -63,6 +63,10 @@ bool MP3Extractor::get_mp3_frame_size(
*out_bitrate = 0;
}
+ if (out_num_samples) {
+ *out_num_samples = 1152;
+ }
+
if ((header & 0xffe00000) != 0xffe00000) {
return false;
}
@@ -127,6 +131,10 @@ bool MP3Extractor::get_mp3_frame_size(
}
*frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+
+ if (out_num_samples) {
+ *out_num_samples = 384;
+ }
} else {
// layer II or III
@@ -150,10 +158,17 @@ bool MP3Extractor::get_mp3_frame_size(
bitrate = (layer == 2 /* L2 */)
? kBitrateV1L2[bitrate_index - 1]
: kBitrateV1L3[bitrate_index - 1];
+
+ if (out_num_samples) {
+ *out_num_samples = 1152;
+ }
} else {
// V2 (or 2.5)
bitrate = kBitrateV2[bitrate_index - 1];
+ if (out_num_samples) {
+ *out_num_samples = 576;
+ }
}
if (out_bitrate) {
@@ -374,6 +389,9 @@ private:
sp<MP3Seeker> mSeeker;
MediaBufferGroup *mGroup;
+ int64_t mBasisTimeUs;
+ int64_t mSamplesRead;
+
MP3Source(const MP3Source &);
MP3Source &operator=(const MP3Source &);
};
@@ -489,7 +507,9 @@ MP3Source::MP3Source(
mCurrentTimeUs(0),
mStarted(false),
mSeeker(seeker),
- mGroup(NULL) {
+ mGroup(NULL),
+ mBasisTimeUs(0),
+ mSamplesRead(0) {
}
MP3Source::~MP3Source() {
@@ -509,6 +529,9 @@ status_t MP3Source::start(MetaData *) {
mCurrentPos = mFirstFramePos;
mCurrentTimeUs = 0;
+ mBasisTimeUs = mCurrentTimeUs;
+ mSamplesRead = 0;
+
mStarted = true;
return OK;
@@ -552,6 +575,9 @@ status_t MP3Source::read(
} else {
mCurrentTimeUs = actualSeekTimeUs;
}
+
+ mBasisTimeUs = mCurrentTimeUs;
+ mSamplesRead = 0;
}
MediaBuffer *buffer;
@@ -562,6 +588,8 @@ status_t MP3Source::read(
size_t frame_size;
int bitrate;
+ int num_samples;
+ int sample_rate;
for (;;) {
ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
if (n < 4) {
@@ -575,7 +603,7 @@ status_t MP3Source::read(
if ((header & kMask) == (mFixedHeader & kMask)
&& MP3Extractor::get_mp3_frame_size(
- header, &frame_size, NULL, NULL, &bitrate)) {
+ header, &frame_size, &sample_rate, NULL, &bitrate, &num_samples)) {
break;
}
@@ -613,7 +641,9 @@ status_t MP3Source::read(
buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
mCurrentPos += frame_size;
- mCurrentTimeUs += frame_size * 8000ll / bitrate;
+
+ mSamplesRead += num_samples;
+ mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate);
*out = buffer;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7b96d01..c79d02e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -19,6 +19,8 @@
#include "include/MPEG4Extractor.h"
#include "include/SampleTable.h"
+#include "include/ESDS.h"
+#include "include/TimedTextPlayer.h"
#include <arpa/inet.h>
@@ -29,7 +31,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/DataSource.h>
-#include "include/ESDS.h"
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -262,7 +263,7 @@ static const char *FourCC2MIME(uint32_t fourcc) {
MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mDataSource(source),
- mHaveMetadata(false),
+ mInitCheck(NO_INIT),
mHasVideo(false),
mFirstTrack(NULL),
mLastTrack(NULL),
@@ -361,8 +362,8 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(
}
status_t MPEG4Extractor::readMetaData() {
- if (mHaveMetadata) {
- return OK;
+ if (mInitCheck != NO_INIT) {
+ return mInitCheck;
}
off64_t offset = 0;
@@ -370,17 +371,20 @@ status_t MPEG4Extractor::readMetaData() {
while ((err = parseChunk(&offset, 0)) == OK) {
}
- if (mHaveMetadata) {
+ if (mInitCheck == OK) {
if (mHasVideo) {
mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
} else {
mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
}
- return OK;
+ mInitCheck = OK;
+ } else {
+ mInitCheck = err;
}
- return err;
+ CHECK_NE(err, (status_t)NO_INIT);
+ return mInitCheck;
}
void MPEG4Extractor::setDrmFlag(bool flag) {
@@ -755,7 +759,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
return err;
}
} else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
- mHaveMetadata = true;
+ mInitCheck = OK;
if (!mIsDrm) {
return UNKNOWN_ERROR; // Return a dummy error.
@@ -829,6 +833,33 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
mLastTrack->meta->setInt64(
kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
+ uint8_t lang[2];
+ off64_t lang_offset;
+ if (version == 1) {
+ lang_offset = timescale_offset + 4 + 8;
+ } else if (version == 0) {
+ lang_offset = timescale_offset + 4 + 4;
+ } else {
+ return ERROR_IO;
+ }
+
+ if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
+ < (ssize_t)sizeof(lang)) {
+ return ERROR_IO;
+ }
+
+ // To get the ISO-639-2/T three character language code
+ // 1 bit pad followed by 3 5-bits characters. Each character
+ // is packed as the difference between its ASCII value and 0x60.
+ char lang_code[4];
+ lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
+ lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
+ lang_code[2] = (lang[1] & 0x1f) + 0x60;
+ lang_code[3] = '\0';
+
+ mLastTrack->meta->setCString(
+ kKeyMediaLanguage, lang_code);
+
*offset += chunk_size;
break;
}
@@ -1292,6 +1323,14 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
return parseDrmSINF(offset, data_offset);
}
+ case FOURCC('t', 'x', '3', 'g'):
+ {
+ mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+
+ *offset += chunk_size;
+ break;
+ }
+
default:
{
*offset += chunk_size;
@@ -1901,7 +1940,7 @@ status_t MPEG4Source::read(
off64_t offset;
size_t size;
- uint32_t dts;
+ uint32_t cts;
bool isSyncSample;
bool newBuffer = false;
if (mBuffer == NULL) {
@@ -1909,7 +1948,7 @@ status_t MPEG4Source::read(
status_t err =
mSampleTable->getMetaDataForSample(
- mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
+ mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
if (err != OK) {
return err;
@@ -1939,7 +1978,7 @@ status_t MPEG4Source::read(
mBuffer->set_range(0, size);
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
- kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+ kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
mBuffer->meta_data()->setInt64(
@@ -2025,14 +2064,18 @@ status_t MPEG4Source::read(
size_t dstOffset = 0;
while (srcOffset < size) {
- CHECK(srcOffset + mNALLengthSize <= size);
- size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
- srcOffset += mNALLengthSize;
+ bool isMalFormed = (srcOffset + mNALLengthSize > size);
+ size_t nalLength = 0;
+ if (!isMalFormed) {
+ nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
+ srcOffset += mNALLengthSize;
+ isMalFormed = srcOffset + nalLength > size;
+ }
- if (srcOffset + nalLength > size) {
+ if (isMalFormed) {
+ LOGE("Video is malformed");
mBuffer->release();
mBuffer = NULL;
-
return ERROR_MALFORMED;
}
@@ -2057,7 +2100,7 @@ status_t MPEG4Source::read(
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
- kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+ kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
mBuffer->meta_data()->setInt64(
@@ -2077,6 +2120,20 @@ status_t MPEG4Source::read(
}
}
+MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
+ const char *mimePrefix) {
+ for (Track *track = mFirstTrack; track != NULL; track = track->next) {
+ const char *mime;
+ if (track->meta != NULL
+ && track->meta->findCString(kKeyMIMEType, &mime)
+ && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
+ return track;
+ }
+ }
+
+ return NULL;
+}
+
static bool LegacySniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
uint8_t header[8];
@@ -2109,6 +2166,11 @@ static bool isCompatibleBrand(uint32_t fourcc) {
FOURCC('3', 'g', 'p', '4'),
FOURCC('m', 'p', '4', '1'),
FOURCC('m', 'p', '4', '2'),
+
+ // Won't promise that the following file types can be played.
+ // Just give these file types a chance.
+ FOURCC('q', 't', ' ', ' '), // Apple's QuickTime
+ FOURCC('M', 'S', 'N', 'V'), // Sony's PSP
};
for (size_t i = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 5d6ea7c..e13b67e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -52,7 +52,7 @@ static const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 600000000LL; // 10 min
class MPEG4Writer::Track {
public:
- Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+ Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
~Track();
@@ -82,6 +82,7 @@ private:
bool mIsAvc;
bool mIsAudio;
bool mIsMPEG4;
+ int32_t mTrackId;
int64_t mTrackDurationUs;
// For realtime applications, we need to adjust the media clock
@@ -231,7 +232,7 @@ MPEG4Writer::MPEG4Writer(const char *filename)
mEstimatedMoovBoxSize(0),
mInterleaveDurationUs(1000000) {
- mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
if (mFd >= 0) {
mInitCheck = OK;
}
@@ -295,7 +296,12 @@ status_t MPEG4Writer::Track::dump(
}
status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
- Track *track = new Track(this, source);
+ Mutex::Autolock l(mLock);
+ if (mStarted) {
+ LOGE("Attempt to add source AFTER recording is started");
+ return UNKNOWN_ERROR;
+ }
+ Track *track = new Track(this, source, mTracks.size());
mTracks.push_back(track);
return OK;
@@ -945,7 +951,7 @@ size_t MPEG4Writer::numTracks() {
////////////////////////////////////////////////////////////////////////////////
MPEG4Writer::Track::Track(
- MPEG4Writer *owner, const sp<MediaSource> &source)
+ MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
: mOwner(owner),
mMeta(source->getFormat()),
mSource(source),
@@ -953,6 +959,7 @@ MPEG4Writer::Track::Track(
mPaused(false),
mResumed(false),
mStarted(false),
+ mTrackId(trackId),
mTrackDurationUs(0),
mEstimatedTrackSizeBytes(0),
mSamplesHaveSameSize(true),
@@ -2030,7 +2037,7 @@ status_t MPEG4Writer::Track::threadEntry() {
(OK != checkCodecSpecificData())) { // no codec specific data
err = ERROR_MALFORMED;
}
- mOwner->trackProgressStatus(this, -1, err);
+ mOwner->trackProgressStatus(mTrackId, -1, err);
// Last chunk
if (mOwner->numTracks() == 1) {
@@ -2077,41 +2084,34 @@ void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
if (mTrackEveryTimeDurationUs > 0 &&
timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
LOGV("Fire time tracking progress status at %lld us", timeUs);
- mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+ mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
mPreviousTrackTimeUs = timeUs;
}
}
void MPEG4Writer::trackProgressStatus(
- const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+ size_t trackId, int64_t timeUs, status_t err) {
Mutex::Autolock lock(mLock);
- int32_t nTracks = mTracks.size();
- CHECK(nTracks >= 1);
- CHECK(nTracks < 64); // Arbitrary number
-
- int32_t trackNum = 0;
- CHECK(trackNum < nTracks);
- trackNum <<= 16;
+ int32_t trackNum = (trackId << 28);
// Error notification
// Do not consider ERROR_END_OF_STREAM an error
if (err != OK && err != ERROR_END_OF_STREAM) {
- notify(MEDIA_RECORDER_EVENT_ERROR,
- trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+ notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
+ trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
err);
return;
}
if (timeUs == -1) {
// Send completion notification
- notify(MEDIA_RECORDER_EVENT_INFO,
- trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
err);
- return;
} else {
// Send progress status
- notify(MEDIA_RECORDER_EVENT_INFO,
- trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
timeUs / 1000);
}
}
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 0be7261..8cd08bc 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -43,7 +43,10 @@ const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav";
const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg";
const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska";
const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS = "video/mp2ts";
+const char *MEDIA_MIMETYPE_CONTAINER_AVI = "video/avi";
const char *MEDIA_MIMETYPE_CONTAINER_WVM = "video/wvm";
+const char *MEDIA_MIMETYPE_TEXT_3GPP = "text/3gpp-tt";
+
} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 23bad5b..af0131e 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
#include "include/MP3Extractor.h"
#include "include/MPEG4Extractor.h"
#include "include/WAVExtractor.h"
@@ -108,6 +109,8 @@ sp<MediaExtractor> MediaExtractor::Create(
ret = new MatroskaExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
ret = new MPEG2TSExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_AVI)) {
+ ret = new AVIExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) {
ret = new WVMExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 248b678..81f2e47 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -323,25 +323,28 @@ void NuCachedSource2::onRead(const sp<AMessage> &msg) {
}
void NuCachedSource2::restartPrefetcherIfNecessary_l(
- bool ignoreLowWaterThreshold) {
+ bool ignoreLowWaterThreshold, bool force) {
static const size_t kGrayArea = 1024 * 1024;
if (mFetching || mFinalStatus != OK) {
return;
}
- if (!ignoreLowWaterThreshold
+ if (!ignoreLowWaterThreshold && !force
&& mCacheOffset + mCache->totalSize() - mLastAccessPos
>= kLowWaterThreshold) {
return;
}
size_t maxBytes = mLastAccessPos - mCacheOffset;
- if (maxBytes < kGrayArea) {
- return;
- }
- maxBytes -= kGrayArea;
+ if (!force) {
+ if (maxBytes < kGrayArea) {
+ return;
+ }
+
+ maxBytes -= kGrayArea;
+ }
size_t actualBytes = mCache->releaseFromStart(maxBytes);
mCacheOffset += actualBytes;
@@ -413,10 +416,19 @@ size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) {
}
ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
+ CHECK_LE(size, (size_t)kHighWaterThreshold);
+
LOGV("readInternal offset %lld size %d", offset, size);
Mutex::Autolock autoLock(mLock);
+ if (!mFetching) {
+ mLastAccessPos = offset;
+ restartPrefetcherIfNecessary_l(
+ false, // ignoreLowWaterThreshold
+ true); // force
+ }
+
if (offset < mCacheOffset
|| offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
static const off64_t kPadding = 256 * 1024;
@@ -438,6 +450,11 @@ ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
}
size_t avail = mCache->totalSize() - delta;
+
+ if (avail > size) {
+ avail = size;
+ }
+
mCache->copy(delta, data, avail);
return avail;
@@ -481,11 +498,11 @@ void NuCachedSource2::resumeFetchingIfNecessary() {
restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
}
-DecryptHandle* NuCachedSource2::DrmInitialization() {
+sp<DecryptHandle> NuCachedSource2::DrmInitialization() {
return mSource->DrmInitialization();
}
-void NuCachedSource2::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
+void NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
mSource->getDrmInfo(handle, client);
}
@@ -493,4 +510,8 @@ String8 NuCachedSource2::getUri() {
return mSource->getUri();
}
+String8 NuCachedSource2::getMIMEType() const {
+ return mSource->getMIMEType();
+}
+
} // namespace android
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 62fb732..821ba9b 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -100,7 +100,6 @@ NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
mNumBandwidthHistoryItems(0),
mTotalTransferTimeUs(0),
mTotalTransferBytes(0),
- mPrevBandwidthMeasureTimeUs(0),
mDecryptHandle(NULL),
mDrmManagerClient(NULL) {
}
@@ -137,6 +136,7 @@ status_t NuHTTPDataSource::connect(
unsigned port;
mUri = uri;
+ mContentType = String8("application/octet-stream");
bool https;
if (!ParseURL(uri, &host, &port, &path, &https)) {
@@ -266,6 +266,15 @@ status_t NuHTTPDataSource::connect(
}
}
+ {
+ AString value;
+ if (mHTTP.find_header_value("Content-Type", &value)) {
+ mContentType = String8(value.c_str());
+ } else {
+ mContentType = String8("application/octet-stream");
+ }
+ }
+
applyTimeoutResponse();
if (offset == 0) {
@@ -535,20 +544,10 @@ void NuHTTPDataSource::addBandwidthMeasurement_l(
mTotalTransferBytes -= entry->mNumBytes;
mBandwidthHistory.erase(mBandwidthHistory.begin());
--mNumBandwidthHistoryItems;
- int64_t timeNowUs = ALooper::GetNowUs();
- if (timeNowUs - mPrevBandwidthMeasureTimeUs > 2000000LL) {
- if (mPrevBandwidthMeasureTimeUs != 0) {
- double estimatedBandwidth =
- ((double)mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
- LOGI("estimated avg bandwidth is %8.2f kbps in the past %lld us",
- estimatedBandwidth, timeNowUs - mPrevBandwidthMeasureTimeUs);
- }
- mPrevBandwidthMeasureTimeUs = timeNowUs;
- }
}
}
-DecryptHandle* NuHTTPDataSource::DrmInitialization() {
+sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
if (mDrmManagerClient == NULL) {
mDrmManagerClient = new DrmManagerClient();
}
@@ -572,8 +571,8 @@ DecryptHandle* NuHTTPDataSource::DrmInitialization() {
return mDecryptHandle;
}
-void NuHTTPDataSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
- *handle = mDecryptHandle;
+void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ handle = mDecryptHandle;
*client = mDrmManagerClient;
}
@@ -582,4 +581,8 @@ String8 NuHTTPDataSource::getUri() {
return mUri;
}
+String8 NuHTTPDataSource::getMIMEType() const {
+ return mContentType;
+}
+
} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 5d26fd5..78d13b2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1830,7 +1830,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
// Dequeue buffers and send them to OMX
for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
- android_native_buffer_t* buf;
+ ANativeWindowBuffer* buf;
err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
if (err != 0) {
LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
@@ -1900,7 +1900,7 @@ status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
// Dequeue the next buffer from the native window.
- android_native_buffer_t* buf;
+ ANativeWindowBuffer* buf;
int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
if (err != 0) {
CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
@@ -1936,6 +1936,11 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
}
void OMXCodec::on_message(const omx_message &msg) {
+ if (mState == ERROR) {
+ LOGW("Dropping OMX message - we're in ERROR state.");
+ return;
+ }
+
switch (msg.type) {
case omx_message::EVENT:
{
@@ -2239,13 +2244,15 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
onPortSettingsChanged(data1);
- } else if (data1 == kPortIndexOutput
- && data2 == OMX_IndexConfigCommonOutputCrop) {
+ } else if (data1 == kPortIndexOutput &&
+ (data2 == OMX_IndexConfigCommonOutputCrop ||
+ data2 == OMX_IndexConfigCommonScale)) {
sp<MetaData> oldOutputFormat = mOutputFormat;
initOutputFormat(mSource->getFormat());
- if (formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
+ if (data2 == OMX_IndexConfigCommonOutputCrop &&
+ formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
mOutputPortSettingsHaveChanged = true;
if (mNativeWindow != NULL) {
@@ -2264,6 +2271,39 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
// already invalid, we'll know soon enough.
native_window_set_crop(mNativeWindow.get(), &crop);
}
+ } else if (data2 == OMX_IndexConfigCommonScale) {
+ OMX_CONFIG_SCALEFACTORTYPE scale;
+ InitOMXParams(&scale);
+ scale.nPortIndex = kPortIndexOutput;
+
+ // Change display dimension only when necessary.
+ if (OK == mOMX->getConfig(
+ mNode,
+ OMX_IndexConfigCommonScale,
+ &scale, sizeof(scale))) {
+ int32_t left, top, right, bottom;
+ CHECK(mOutputFormat->findRect(kKeyCropRect,
+ &left, &top,
+ &right, &bottom));
+
+ // The scale is in 16.16 format.
+ // scale 1.0 = 0x010000. When there is no
+ // need to change the display, skip it.
+ LOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
+ scale.xWidth, scale.xHeight);
+
+ if (scale.xWidth != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayWidth,
+ ((right - left + 1) * scale.xWidth) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+
+ if (scale.xHeight != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayHeight,
+ ((bottom - top + 1) * scale.xHeight) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+ }
}
}
break;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 423df70..ef4d3d0 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -53,6 +53,7 @@ SampleTable::SampleTable(const sp<DataSource> &source)
mNumSampleSizes(0),
mTimeToSampleCount(0),
mTimeToSample(NULL),
+ mSampleTimeEntries(NULL),
mCompositionTimeDeltaEntries(NULL),
mNumCompositionTimeDeltaEntries(0),
mSyncSampleOffset(-1),
@@ -73,6 +74,9 @@ SampleTable::~SampleTable() {
delete[] mCompositionTimeDeltaEntries;
mCompositionTimeDeltaEntries = NULL;
+ delete[] mSampleTimeEntries;
+ mSampleTimeEntries = NULL;
+
delete[] mTimeToSample;
mTimeToSample = NULL;
@@ -381,67 +385,132 @@ uint32_t abs_difference(uint32_t time1, uint32_t time2) {
return time1 > time2 ? time1 - time2 : time2 - time1;
}
-status_t SampleTable::findSampleAtTime(
- uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
- // XXX this currently uses decoding time, instead of composition time.
+// static
+int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
+ const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
+ const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
- *sample_index = 0;
+ if (a->mCompositionTime < b->mCompositionTime) {
+ return -1;
+ } else if (a->mCompositionTime > b->mCompositionTime) {
+ return 1;
+ }
+
+ return 0;
+}
+void SampleTable::buildSampleEntriesTable() {
Mutex::Autolock autoLock(mLock);
- uint32_t cur_sample = 0;
- uint32_t time = 0;
+ if (mSampleTimeEntries != NULL) {
+ return;
+ }
+
+ mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
+
+ uint32_t sampleIndex = 0;
+ uint32_t sampleTime = 0;
+
for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
uint32_t n = mTimeToSample[2 * i];
uint32_t delta = mTimeToSample[2 * i + 1];
- if (req_time < time + n * delta) {
- int j = (req_time - time) / delta;
-
- uint32_t time1 = time + j * delta;
- uint32_t time2 = time1 + delta;
-
- uint32_t sampleTime;
- if (i+1 == mTimeToSampleCount
- || (abs_difference(req_time, time1)
- < abs_difference(req_time, time2))) {
- *sample_index = cur_sample + j;
- sampleTime = time1;
- } else {
- *sample_index = cur_sample + j + 1;
- sampleTime = time2;
- }
+ for (uint32_t j = 0; j < n; ++j) {
+ CHECK(sampleIndex < mNumSampleSizes);
- switch (flags) {
- case kFlagBefore:
- {
- if (sampleTime > req_time && *sample_index > 0) {
- --*sample_index;
- }
- break;
- }
+ mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
- case kFlagAfter:
- {
- if (sampleTime < req_time
- && *sample_index + 1 < mNumSampleSizes) {
- ++*sample_index;
- }
- break;
- }
+ mSampleTimeEntries[sampleIndex].mCompositionTime =
+ sampleTime + getCompositionTimeOffset(sampleIndex);
+
+ ++sampleIndex;
+ sampleTime += delta;
+ }
+ }
+
+ qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
+ CompareIncreasingTime);
+}
- default:
- break;
+status_t SampleTable::findSampleAtTime(
+ uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
+ buildSampleEntriesTable();
+
+ uint32_t left = 0;
+ uint32_t right = mNumSampleSizes;
+ while (left < right) {
+ uint32_t center = (left + right) / 2;
+ uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
+
+ if (req_time < centerTime) {
+ right = center;
+ } else if (req_time > centerTime) {
+ left = center + 1;
+ } else {
+ left = center;
+ break;
+ }
+ }
+
+ if (left == mNumSampleSizes) {
+ if (flags == kFlagAfter) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ --left;
+ }
+
+ uint32_t closestIndex = left;
+
+ switch (flags) {
+ case kFlagBefore:
+ {
+ while (closestIndex > 0
+ && mSampleTimeEntries[closestIndex].mCompositionTime
+ > req_time) {
+ --closestIndex;
}
+ break;
+ }
- return OK;
+ case kFlagAfter:
+ {
+ while (closestIndex + 1 < mNumSampleSizes
+ && mSampleTimeEntries[closestIndex].mCompositionTime
+ < req_time) {
+ ++closestIndex;
+ }
+ break;
}
- time += delta * n;
- cur_sample += n;
+ default:
+ {
+ CHECK(flags == kFlagClosest);
+
+ if (closestIndex > 0) {
+ // Check left neighbour and pick closest.
+ uint32_t absdiff1 =
+ abs_difference(
+ mSampleTimeEntries[closestIndex].mCompositionTime,
+ req_time);
+
+ uint32_t absdiff2 =
+ abs_difference(
+ mSampleTimeEntries[closestIndex - 1].mCompositionTime,
+ req_time);
+
+ if (absdiff1 > absdiff2) {
+ closestIndex = closestIndex - 1;
+ }
+ }
+
+ break;
+ }
}
- return ERROR_OUT_OF_RANGE;
+ *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
+
+ return OK;
}
status_t SampleTable::findSyncSampleNear(
@@ -613,7 +682,7 @@ status_t SampleTable::getMetaDataForSample(
uint32_t sampleIndex,
off64_t *offset,
size_t *size,
- uint32_t *decodingTime,
+ uint32_t *compositionTime,
bool *isSyncSample) {
Mutex::Autolock autoLock(mLock);
@@ -630,8 +699,8 @@ status_t SampleTable::getMetaDataForSample(
*size = mSampleIterator->getSampleSize();
}
- if (decodingTime) {
- *decodingTime = mSampleIterator->getSampleTime();
+ if (compositionTime) {
+ *compositionTime = mSampleIterator->getSampleTime();
}
if (isSyncSample) {
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 84f65ff..f82ff32 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -37,7 +37,8 @@ static bool FileHasAcceptableExtension(const char *extension) {
".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
- ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac"
+ ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
+ ".avi",
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -124,7 +125,8 @@ status_t StagefrightMediaScanner::processFile(
|| !strcasecmp(extension, ".xmf")
|| !strcasecmp(extension, ".rtttl")
|| !strcasecmp(extension, ".rtx")
- || !strcasecmp(extension, ".ota")) {
+ || !strcasecmp(extension, ".ota")
+ || !strcasecmp(extension, ".mxmf")) {
status_t status = HandleMIDI(path, &client);
if (status != OK) {
return status;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index ea3b801..4c3dc47 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -27,6 +27,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/MediaDefs.h>
namespace android {
@@ -48,7 +49,8 @@ StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
mClient.disconnect();
}
-status_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
+status_t StagefrightMetadataRetriever::setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
LOGV("setDataSource(%s)", uri);
mParsedMetaData = false;
@@ -56,7 +58,7 @@ status_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
delete mAlbumArt;
mAlbumArt = NULL;
- mSource = DataSource::CreateFromURI(uri);
+ mSource = DataSource::CreateFromURI(uri, headers);
if (mSource == NULL) {
return UNKNOWN_ERROR;
@@ -145,7 +147,8 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
int64_t thumbNailTime;
if (frameTimeUs < 0) {
- if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+ if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
+ || thumbNailTime < 0) {
thumbNailTime = 0;
}
options.setSeekTo(thumbNailTime, mode);
@@ -231,6 +234,14 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
frame->mData = new uint8_t[frame->mSize];
frame->mRotationAngle = rotationAngle;
+ int32_t displayWidth, displayHeight;
+ if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+ frame->mDisplayWidth = displayWidth;
+ }
+ if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+ frame->mDisplayHeight = displayHeight;
+ }
+
int32_t srcFormat;
CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
@@ -411,8 +422,15 @@ void StagefrightMetadataRetriever::parseMetaData() {
mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
+ bool hasAudio = false;
+ bool hasVideo = false;
+ int32_t videoWidth = -1;
+ int32_t videoHeight = -1;
+ int32_t audioBitrate = -1;
+
// The overall duration is the duration of the longest track.
int64_t maxDurationUs = 0;
+ String8 timedTextLang;
for (size_t i = 0; i < numTracks; ++i) {
sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
@@ -422,12 +440,67 @@ void StagefrightMetadataRetriever::parseMetaData() {
maxDurationUs = durationUs;
}
}
+
+ const char *mime;
+ if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+ if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+ hasAudio = true;
+
+ if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+ audioBitrate = -1;
+ }
+ } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+ hasVideo = true;
+
+ CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+ CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ const char *lang;
+ trackMeta->findCString(kKeyMediaLanguage, &lang);
+ timedTextLang.append(String8(lang));
+ timedTextLang.append(String8(":"));
+ }
+ }
+ }
+
+ // To save the language codes for all timed text tracks
+ // If multiple text tracks present, the format will look
+ // like "eng:chi"
+ if (!timedTextLang.isEmpty()) {
+ mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
}
// The duration value is a string representing the duration in ms.
sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
+ if (hasAudio) {
+ mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+ }
+
+ if (hasVideo) {
+ mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+ sprintf(tmp, "%d", videoWidth);
+ mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+ sprintf(tmp, "%d", videoHeight);
+ mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+ }
+
+ if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+ sprintf(tmp, "%d", audioBitrate);
+ mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+ } else {
+ off64_t sourceSize;
+ if (mSource->getSize(&sourceSize) == OK) {
+ int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+ sprintf(tmp, "%lld", avgBitRate);
+ mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+ }
+ }
+
if (numTracks == 1) {
const char *fileMIME;
CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
diff --git a/media/libstagefright/TimedTextPlayer.cpp b/media/libstagefright/TimedTextPlayer.cpp
new file mode 100644
index 0000000..1ac22cb
--- /dev/null
+++ b/media/libstagefright/TimedTextPlayer.cpp
@@ -0,0 +1,252 @@
+ /*
+ * Copyright (C) 2011 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 "TimedTextPlayer"
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/Utils.h>
+#include "include/AwesomePlayer.h"
+#include "include/TimedTextPlayer.h"
+
+namespace android {
+
+struct TimedTextEvent : public TimedEventQueue::Event {
+ TimedTextEvent(
+ TimedTextPlayer *player,
+ void (TimedTextPlayer::*method)())
+ : mPlayer(player),
+ mMethod(method) {
+ }
+
+protected:
+ virtual ~TimedTextEvent() {}
+
+ virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+ (mPlayer->*mMethod)();
+ }
+
+private:
+ TimedTextPlayer *mPlayer;
+ void (TimedTextPlayer::*mMethod)();
+
+ TimedTextEvent(const TimedTextEvent &);
+ TimedTextEvent &operator=(const TimedTextEvent &);
+};
+
+TimedTextPlayer::TimedTextPlayer(
+ AwesomePlayer *observer,
+ const wp<MediaPlayerBase> &listener,
+ TimedEventQueue *queue)
+ : mSource(NULL),
+ mSeekTimeUs(0),
+ mStarted(false),
+ mTextEventPending(false),
+ mQueue(queue),
+ mListener(listener),
+ mObserver(observer),
+ mTextBuffer(NULL) {
+ mTextEvent = new TimedTextEvent(this, &TimedTextPlayer::onTextEvent);
+}
+
+TimedTextPlayer::~TimedTextPlayer() {
+ if (mStarted) {
+ reset();
+ }
+
+ mTextTrackVector.clear();
+}
+
+status_t TimedTextPlayer::start(uint8_t index) {
+ CHECK(!mStarted);
+
+ if (index >= mTextTrackVector.size()) {
+ LOGE("Incorrect text track index");
+ return BAD_VALUE;
+ }
+
+ mSource = mTextTrackVector.itemAt(index);
+
+ status_t err = mSource->start();
+
+ if (err != OK) {
+ return err;
+ }
+
+ int64_t positionUs;
+ mObserver->getPosition(&positionUs);
+ seekTo(positionUs);
+
+ postTextEvent();
+
+ mStarted = true;
+
+ return OK;
+}
+
+void TimedTextPlayer::pause() {
+ CHECK(mStarted);
+
+ cancelTextEvent();
+}
+
+void TimedTextPlayer::resume() {
+ CHECK(mStarted);
+
+ postTextEvent();
+}
+
+void TimedTextPlayer::reset() {
+ CHECK(mStarted);
+
+ // send an empty text to clear the screen
+ notifyListener(MEDIA_TIMED_TEXT);
+
+ cancelTextEvent();
+
+ mSeeking = false;
+ mStarted = false;
+
+ if (mTextBuffer != NULL) {
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+ }
+
+ if (mSource != NULL) {
+ mSource->stop();
+ mSource.clear();
+ mSource = NULL;
+ }
+}
+
+status_t TimedTextPlayer::seekTo(int64_t time_us) {
+ Mutex::Autolock autoLock(mLock);
+
+ mSeeking = true;
+ mSeekTimeUs = time_us;
+
+ return OK;
+}
+
+status_t TimedTextPlayer::setTimedTextTrackIndex(int32_t index) {
+ if (index >= (int)(mTextTrackVector.size())) {
+ return BAD_VALUE;
+ }
+
+ if (mStarted) {
+ reset();
+ }
+
+ if (index >= 0) {
+ return start(index);
+ }
+ return OK;
+}
+
+void TimedTextPlayer::onTextEvent() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (!mTextEventPending) {
+ return;
+ }
+ mTextEventPending = false;
+
+ MediaSource::ReadOptions options;
+ if (mSeeking) {
+ options.setSeekTo(mSeekTimeUs,
+ MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+ mSeeking = false;
+
+ if (mTextBuffer != NULL) {
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+ }
+
+ notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen
+ }
+
+ if (mTextBuffer != NULL) {
+ uint8_t *tmp = (uint8_t *)(mTextBuffer->data());
+ size_t len = (*tmp) << 8 | (*(tmp + 1));
+
+ notifyListener(MEDIA_TIMED_TEXT,
+ tmp + 2,
+ len);
+
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+
+ }
+
+ if (mSource->read(&mTextBuffer, &options) != OK) {
+ return;
+ }
+
+ int64_t positionUs, timeUs;
+ mObserver->getPosition(&positionUs);
+ mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
+
+ //send the text now
+ if (timeUs <= positionUs + 100000ll) {
+ postTextEvent();
+ } else {
+ postTextEvent(timeUs - positionUs - 100000ll);
+ }
+}
+
+void TimedTextPlayer::postTextEvent(int64_t delayUs) {
+ if (mTextEventPending) {
+ return;
+ }
+
+ mTextEventPending = true;
+ mQueue->postEventWithDelay(mTextEvent, delayUs < 0 ? 10000 : delayUs);
+}
+
+void TimedTextPlayer::cancelTextEvent() {
+ mQueue->cancelEvent(mTextEvent->eventID());
+ mTextEventPending = false;
+}
+
+void TimedTextPlayer::addTextSource(sp<MediaSource> source) {
+ mTextTrackVector.add(source);
+}
+
+void TimedTextPlayer::notifyListener(
+ int msg, const void *data, size_t size) {
+ if (mListener != NULL) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+
+ if (listener != NULL) {
+ if (size > 0) {
+ mData.freeData();
+ mData.write(data, size);
+
+ listener->sendEvent(msg, 0, 0, &mData);
+ } else { // send an empty timed text to clear the screen
+ listener->sendEvent(msg);
+ }
+ }
+ }
+}
+}
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 9332120..76f47f7 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -353,8 +353,6 @@ status_t WAVSource::read(
return ERROR_END_OF_STREAM;
}
- mCurrentPos += n;
-
buffer->set_range(0, n);
if (mWaveFormat == WAVE_FORMAT_PCM) {
@@ -406,6 +404,7 @@ status_t WAVSource::read(
/ (mNumChannels * bytesPerSample) / mSampleRate);
buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mCurrentPos += n;
*out = buffer;
@@ -426,6 +425,11 @@ bool SniffWAV(
return false;
}
+ sp<MediaExtractor> extractor = new WAVExtractor(source);
+ if (extractor->countTracks() == 0) {
+ return false;
+ }
+
*mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
*confidence = 0.3f;
diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp
index 616836c..0d0d6c2 100644
--- a/media/libstagefright/XINGSeeker.cpp
+++ b/media/libstagefright/XINGSeeker.cpp
@@ -41,8 +41,6 @@ sp<XINGSeeker> XINGSeeker::CreateFromSource(
return NULL;
}
- LOGI("Found XING header.");
-
return seeker;
}
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
new file mode 100644
index 0000000..80b2478
--- /dev/null
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ ChromiumHTTPDataSource.cpp \
+ support.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/base/include/media/stagefright/openmax \
+ external/chromium \
+ external/chromium/android
+
+LOCAL_CFLAGS += -Wno-multichar
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_MODULE:= libstagefright_chromium_http
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..1096717
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2011 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 "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+ : mFlags(flags),
+ mState(DISCONNECTED),
+ mDelegate(new SfDelegate),
+ mCurrentOffset(0),
+ mIOResult(OK),
+ mContentSize(-1),
+ mNumBandwidthHistoryItems(0),
+ mTotalTransferTimeUs(0),
+ mTotalTransferBytes(0),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
+ mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+ disconnect();
+
+ delete mDelegate;
+ mDelegate = NULL;
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ if (mState != DISCONNECTED) {
+ disconnect_l();
+ }
+
+ if (!(mFlags & kFlagIncognito)) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+ } else {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+ "connect to <URL suppressed> @%lld", offset);
+ }
+
+ mURI = uri;
+ mContentType = String8("application/octet-stream");
+
+ if (headers != NULL) {
+ mHeaders = *headers;
+ } else {
+ mHeaders.clear();
+ }
+
+ mState = CONNECTING;
+ mContentSize = -1;
+ mCurrentOffset = offset;
+
+ mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+ while (mState == CONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(
+ int64_t contentSize, const char *contentType) {
+ Mutex::Autolock autoLock(mLock);
+ mState = CONNECTED;
+ mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+ mContentType = String8(contentType);
+ mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+ mState = DISCONNECTED;
+ mCondition.broadcast();
+
+ mURI.clear();
+
+ mIOResult = err;
+
+ clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+ Mutex::Autolock autoLock(mLock);
+ disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+ if (mState == DISCONNECTED) {
+ return;
+ }
+
+ mState = DISCONNECTING;
+ mIOResult = -EINTR;
+
+ mDelegate->initiateDisconnect();
+
+ while (mState == DISCONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
+ return ERROR_NOT_CONNECTED;
+ }
+
+ if (offset != mCurrentOffset) {
+ AString tmp = mURI;
+ KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+ disconnect_l();
+
+ status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mState = READING;
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ mDelegate->initiateRead(data, size);
+
+ while (mState == READING) {
+ mCondition.wait(mLock);
+ }
+
+ if (mIOResult < OK) {
+ return mIOResult;
+ }
+
+ if (mState == CONNECTED) {
+ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+ // The read operation was successful, mIOResult contains
+ // the number of bytes read.
+ addBandwidthMeasurement_l(mIOResult, delayUs);
+
+ mCurrentOffset += mIOResult;
+ return mIOResult;
+ }
+
+ return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ mIOResult = size;
+
+ if (mState == READING) {
+ mState = CONNECTED;
+ mCondition.broadcast();
+ }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mContentSize < 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ *size = mContentSize;
+
+ return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+ return kWantsPrefetching;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size) {
+ me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+ mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+ Mutex::Autolock autoLock(mLock);
+ CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+ mState = DISCONNECTED;
+ mURI.clear();
+
+ mCondition.broadcast();
+
+ clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::addBandwidthMeasurement_l(
+ size_t numBytes, int64_t delayUs) {
+ BandwidthEntry entry;
+ entry.mDelayUs = delayUs;
+ entry.mNumBytes = numBytes;
+ mTotalTransferTimeUs += delayUs;
+ mTotalTransferBytes += numBytes;
+
+ mBandwidthHistory.push_back(entry);
+ if (++mNumBandwidthHistoryItems > 100) {
+ BandwidthEntry *entry = &*mBandwidthHistory.begin();
+ mTotalTransferTimeUs -= entry->mDelayUs;
+ mTotalTransferBytes -= entry->mNumBytes;
+ mBandwidthHistory.erase(mBandwidthHistory.begin());
+ --mNumBandwidthHistoryItems;
+ }
+}
+
+bool ChromiumHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mNumBandwidthHistoryItems < 2) {
+ return false;
+ }
+
+ *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+ return true;
+}
+
+sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
+ return NULL;
+ }
+
+ if (mDecryptHandle == NULL) {
+ /* Note if redirect occurs, mUri is the redirect uri instead of the
+ * original one
+ */
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ String8(mURI.c_str()));
+ }
+
+ if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+ sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ Mutex::Autolock autoLock(mLock);
+
+ handle = mDecryptHandle;
+ *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+ Mutex::Autolock autoLock(mLock);
+
+ return String8(mURI.c_str());
+}
+
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mContentType;
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
new file mode 100644
index 0000000..af2f6ac
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2011 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 "ChromiumHTTPDataSourceSupport"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "support.h"
+
+#include "android/net/android_network_library_impl.h"
+#include "base/thread.h"
+#include "net/base/host_resolver.h"
+#include "net/base/ssl_config_service.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/proxy/proxy_config_service_android.h"
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static Mutex gNetworkThreadLock;
+static base::Thread *gNetworkThread = NULL;
+static scoped_refptr<URLRequestContext> gReqContext;
+
+static void InitializeNetworkThreadIfNecessary() {
+ Mutex::Autolock autoLock(gNetworkThreadLock);
+ if (gNetworkThread == NULL) {
+ gNetworkThread = new base::Thread("network");
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ CHECK(gNetworkThread->StartWithOptions(options));
+
+ gReqContext = new SfRequestContext;
+
+ net::AndroidNetworkLibrary::RegisterSharedInstance(
+ new SfNetworkLibrary);
+ }
+}
+
+static void MY_LOGI(const char *s) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
+}
+
+static void MY_LOGV(const char *s) {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+ LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
+#endif
+}
+
+SfNetLog::SfNetLog()
+ : mNextID(1) {
+}
+
+void SfNetLog::AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params) {
+#if 0
+ MY_LOGI(StringPrintf(
+ "AddEntry time=%s type=%s source=%s phase=%s\n",
+ TickCountToString(time).c_str(),
+ EventTypeToString(type),
+ SourceTypeToString(source.type),
+ EventPhaseToString(phase)).c_str());
+#endif
+}
+
+uint32 SfNetLog::NextID() {
+ return mNextID++;
+}
+
+net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
+ return LOG_ALL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfRequestContext::SfRequestContext() {
+ AString ua;
+ ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.version.release", value, "Unknown");
+ ua.append(value);
+ ua.append(")");
+
+ mUserAgent = ua.c_str();
+
+ net_log_ = new SfNetLog;
+
+ host_resolver_ =
+ net::CreateSystemHostResolver(
+ net::HostResolver::kDefaultParallelism,
+ NULL /* resolver_proc */,
+ net_log_);
+
+ ssl_config_service_ =
+ net::SSLConfigService::CreateSystemSSLConfigService();
+
+ proxy_service_ = net::ProxyService::CreateWithoutProxyResolver(
+ new net::ProxyConfigServiceAndroid, net_log_);
+
+ http_transaction_factory_ = new net::HttpCache(
+ host_resolver_,
+ dnsrr_resolver_,
+ dns_cert_checker_.get(),
+ proxy_service_.get(),
+ ssl_config_service_.get(),
+ net::HttpAuthHandlerFactory::CreateDefault(host_resolver_),
+ network_delegate_,
+ net_log_,
+ NULL); // backend_factory
+}
+
+const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
+ return mUserAgent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfNetworkLibrary::SfNetworkLibrary() {}
+
+SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type) {
+ return VERIFY_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfDelegate::SfDelegate()
+ : mOwner(NULL),
+ mURLRequest(NULL),
+ mReadBuffer(new net::IOBufferWithSize(8192)),
+ mNumBytesRead(0),
+ mNumBytesTotal(0),
+ mDataDestination(NULL),
+ mAtEOS(false) {
+ InitializeNetworkThreadIfNecessary();
+}
+
+SfDelegate::~SfDelegate() {
+ CHECK(mURLRequest == NULL);
+}
+
+void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
+ mOwner = owner;
+}
+
+void SfDelegate::OnReceivedRedirect(
+ URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+ MY_LOGI("OnReceivedRedirect");
+}
+
+void SfDelegate::OnAuthRequired(
+ URLRequest *request, net::AuthChallengeInfo *auth_info) {
+ MY_LOGI("OnAuthRequired");
+
+ inherited::OnAuthRequired(request, auth_info);
+}
+
+void SfDelegate::OnCertificateRequested(
+ URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
+ MY_LOGI("OnCertificateRequested");
+
+ inherited::OnCertificateRequested(request, cert_request_info);
+}
+
+void SfDelegate::OnSSLCertificateError(
+ URLRequest *request, int cert_error, net::X509Certificate *cert) {
+ fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
+
+ inherited::OnSSLCertificateError(request, cert_error, cert);
+}
+
+void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) {
+ MY_LOGI("OnGetCookies");
+}
+
+void SfDelegate::OnSetCookie(
+ URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy) {
+ MY_LOGI("OnSetCookie");
+}
+
+void SfDelegate::OnResponseStarted(URLRequest *request) {
+ if (request->status().status() != URLRequestStatus::SUCCESS) {
+ MY_LOGI(StringPrintf(
+ "Request failed with status %d and os_error %d",
+ request->status().status(),
+ request->status().os_error()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ } else if (mRangeRequested && request->GetResponseCode() != 206) {
+ MY_LOGI(StringPrintf(
+ "We requested a content range, but server didn't "
+ "support that. (responded with %d)",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(-EPIPE);
+ return;
+ } else if ((request->GetResponseCode() / 100) != 2) {
+ MY_LOGI(StringPrintf(
+ "Server responded with http status %d",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV("OnResponseStarted");
+
+ std::string headers;
+ request->GetAllResponseHeaders(&headers);
+
+ MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
+
+ std::string contentType;
+ request->GetResponseHeaderByName("Content-Type", &contentType);
+
+ mOwner->onConnectionEstablished(
+ request->GetExpectedContentSize(), contentType.c_str());
+}
+
+void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
+ if (bytes_read == -1) {
+ MY_LOGI(StringPrintf(
+ "OnReadCompleted, read failed, status %d",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
+
+ if (bytes_read < 0) {
+ MY_LOGI(StringPrintf(
+ "Read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ } else if (bytes_read == 0) {
+ mAtEOS = true;
+ mOwner->onReadCompleted(mNumBytesRead);
+ return;
+ }
+
+ CHECK_GT(bytes_read, 0);
+ CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ bytes_read);
+
+ mNumBytesRead += bytes_read;
+
+ readMore(request);
+}
+
+void SfDelegate::readMore(URLRequest *request) {
+ while (mNumBytesRead < mNumBytesTotal) {
+ size_t copy = mNumBytesTotal - mNumBytesRead;
+ if (copy > mReadBuffer->size()) {
+ copy = mReadBuffer->size();
+ }
+
+ int n;
+ if (request->Read(mReadBuffer, copy, &n)) {
+ MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
+
+ CHECK_LE((size_t)n, copy);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ n);
+
+ mNumBytesRead += n;
+
+ if (n == 0) {
+ mAtEOS = true;
+ break;
+ }
+ } else {
+ MY_LOGV("readMore pending read");
+
+ if (request->status().status() != URLRequestStatus::IO_PENDING) {
+ MY_LOGI(StringPrintf(
+ "Direct read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ return;
+ }
+ }
+
+ mOwner->onReadCompleted(mNumBytesRead);
+}
+
+void SfDelegate::initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ GURL url(uri);
+
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateConnectionWrapper,
+ this,
+ url,
+ headers,
+ offset));
+
+}
+
+// static
+void SfDelegate::OnInitiateConnectionWrapper(
+ SfDelegate *me, GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ me->onInitiateConnection(url, headers, offset);
+}
+
+void SfDelegate::onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *extra,
+ off64_t offset) {
+ CHECK(mURLRequest == NULL);
+
+ mURLRequest = new URLRequest(url, this);
+ mAtEOS = false;
+
+ mRangeRequested = false;
+
+ if (offset != 0 || extra != NULL) {
+ net::HttpRequestHeaders headers =
+ mURLRequest->extra_request_headers();
+
+ if (offset != 0) {
+ headers.AddHeaderFromString(
+ StringPrintf("Range: bytes=%lld-", offset).c_str());
+
+ mRangeRequested = true;
+ }
+
+ if (extra != NULL) {
+ for (size_t i = 0; i < extra->size(); ++i) {
+ AString s;
+ s.append(extra->keyAt(i).string());
+ s.append(": ");
+ s.append(extra->valueAt(i).string());
+
+ headers.AddHeaderFromString(s.c_str());
+ }
+ }
+
+ mURLRequest->SetExtraRequestHeaders(headers);
+ }
+
+ mURLRequest->set_context(gReqContext);
+
+ mURLRequest->Start();
+}
+
+void SfDelegate::initiateDisconnect() {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateDisconnectWrapper, this));
+}
+
+// static
+void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
+ me->onInitiateDisconnect();
+}
+
+void SfDelegate::onInitiateDisconnect() {
+ mURLRequest->Cancel();
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onDisconnectComplete();
+}
+
+void SfDelegate::initiateRead(void *data, size_t size) {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateReadWrapper, this, data, size));
+}
+
+// static
+void SfDelegate::OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size) {
+ me->onInitiateRead(data, size);
+}
+
+void SfDelegate::onInitiateRead(void *data, size_t size) {
+ CHECK(mURLRequest != NULL);
+
+ mNumBytesRead = 0;
+ mNumBytesTotal = size;
+ mDataDestination = data;
+
+ if (mAtEOS) {
+ mOwner->onReadCompleted(0);
+ return;
+ }
+
+ readMore(mURLRequest);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
new file mode 100644
index 0000000..634ac93
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 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 SUPPORT_H_
+
+#define SUPPORT_H_
+
+#include <assert.h>
+
+#include "net/base/net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/base/android_network_library.h"
+#include "net/base/io_buffer.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct SfNetLog : public net::NetLog {
+ SfNetLog();
+
+ virtual void AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params);
+
+ virtual uint32 NextID();
+ virtual LogLevel GetLogLevel() const;
+
+private:
+ uint32 mNextID;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetLog);
+};
+
+struct SfRequestContext : public URLRequestContext {
+ SfRequestContext();
+
+ virtual const std::string &GetUserAgent(const GURL &url) const;
+
+private:
+ std::string mUserAgent;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
+};
+
+// This is required for https support, we don't really verify certificates,
+// we accept anything...
+struct SfNetworkLibrary : public net::AndroidNetworkLibrary {
+ SfNetworkLibrary();
+
+ virtual VerifyResult VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary);
+};
+
+struct ChromiumHTTPDataSource;
+
+struct SfDelegate : public URLRequest::Delegate {
+ SfDelegate();
+ virtual ~SfDelegate();
+
+ void initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void initiateDisconnect();
+ void initiateRead(void *data, size_t size);
+
+ void setOwner(ChromiumHTTPDataSource *mOwner);
+
+ virtual void OnReceivedRedirect(
+ URLRequest *request, const GURL &new_url, bool *defer_redirect);
+
+ virtual void OnAuthRequired(
+ URLRequest *request, net::AuthChallengeInfo *auth_info);
+
+ virtual void OnCertificateRequested(
+ URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+
+ virtual void OnSSLCertificateError(
+ URLRequest *request, int cert_error, net::X509Certificate *cert);
+
+ virtual void OnGetCookies(URLRequest *request, bool blocked_by_policy);
+
+ virtual void OnSetCookie(
+ URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy);
+
+ virtual void OnResponseStarted(URLRequest *request);
+
+ virtual void OnReadCompleted(URLRequest *request, int bytes_read);
+
+private:
+ typedef Delegate inherited;
+
+ ChromiumHTTPDataSource *mOwner;
+
+ URLRequest *mURLRequest;
+ scoped_refptr<net::IOBufferWithSize> mReadBuffer;
+
+ size_t mNumBytesRead;
+ size_t mNumBytesTotal;
+ void *mDataDestination;
+
+ bool mRangeRequested;
+ bool mAtEOS;
+
+ void readMore(URLRequest *request);
+
+ static void OnInitiateConnectionWrapper(
+ SfDelegate *me,
+ GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ static void OnInitiateDisconnectWrapper(SfDelegate *me);
+
+ static void OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size);
+
+ void onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void onInitiateDisconnect();
+ void onInitiateRead(void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfDelegate);
+};
+
+} // namespace android
+
+#endif // SUPPORT_H_
diff --git a/media/libstagefright/codecs/aacdec/sbr_dec.cpp b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
index 8fcc3ce..8519b17 100644
--- a/media/libstagefright/codecs/aacdec/sbr_dec.cpp
+++ b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
@@ -1,5 +1,5 @@
/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
+ * Copyright (C) 1998-2010 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -447,7 +447,12 @@ void sbr_dec(Int16 *inPcmData,
if (xoverBand > sbrDec->highSubband)
{
- xoverBand = 32; /* error condition, default to upsampling mode */
+ /*
+ * error condition, default to upsampling mode
+ * and make sure that the number of bands for xover does
+ * not exceed the number of high freq bands.
+ */
+ xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
}
m = sbrDec->bufReadOffs + i; /* 2 + i */
@@ -558,18 +563,22 @@ void sbr_dec(Int16 *inPcmData,
/*
* Set Circular buffer for PS hybrid analysis
*/
+
+ int32_t *pt_temp = &scratch_mem[2][32];
+
for (i = 0, j = 0; i < 3; i++)
{
- pv_memmove(&scratch_mem[2][32 + j ],
+ pv_memmove(&pt_temp[ j],
hParametricStereoDec->hHybrid->mQmfBufferReal[i],
HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
- pv_memmove(&scratch_mem[2][32 + j + 44],
+ pv_memmove(&pt_temp[ j + 44],
hParametricStereoDec->hHybrid->mQmfBufferImag[i],
HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
j += 88;
}
+
pv_memset((void *)&qmf_PS_generated_Real[hParametricStereoDec->usb],
0,
(64 - hParametricStereoDec->usb)*sizeof(*qmf_PS_generated_Real));
@@ -626,19 +635,23 @@ void sbr_dec(Int16 *inPcmData,
* Save Circular buffer history used on PS hybrid analysis
*/
+
+ pt_temp = &scratch_mem[2][64];
+
for (i = 0, j = 0; i < 3; i++)
{
pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferReal[i],
- &scratch_mem[2][ 64 + j ],
+ &pt_temp[ j],
HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferImag[i],
- &scratch_mem[2][ 64 + j + 44],
+ &pt_temp[ j + 44],
HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
j += 88;
}
+
pv_memmove(hFrameData->V, &circular_buffer_s[0], 1152*sizeof(*circular_buffer_s));
/*
@@ -746,7 +759,12 @@ void sbr_dec(Int16 *inPcmData,
if (xoverBand > sbrDec->highSubband)
{
- xoverBand = 32; /* error condition, default to upsampling mode */
+ /*
+ * error condition, default to upsampling mode
+ * and make sure that the number of bands for xover does
+ * not exceed the number of high freq bands.
+ */
+ xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
}
}
else
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
index cda4f9d..f9cc6a3 100644
--- a/media/libstagefright/codecs/aacenc/Android.mk
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
-LOCAL_PRELINK_MODULE := false
+
LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
index 64d012d..774da7b 100644
--- a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
+++ b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
@@ -188,7 +188,7 @@ int main(int argc, char **argv)
useData.memflag = VO_IMF_USERMEMOPERATOR;
useData.memData = (VO_PTR)(&moper);
// open encoder dll;
- handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW);
+ handle = dlopen("libstagefright.so", RTLD_NOW);
if(handle == 0)
{
printf("open dll error......");
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
index 52c9c07..ba3f4d2 100644
--- a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
+++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
@@ -1,24 +1,25 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := AAC_E_SAMPLES.c
-
-LOCAL_SRC_FILES += \
- ../../../Common/cmnMemory.c
+LOCAL_SRC_FILES := \
+ AAC_E_SAMPLES.c \
+ ../../common/cmnMemory.c
-LOCAL_MODULE := TestvoAACEnc
+LOCAL_CFLAGS += $(VO_CFLAGS)
-LOCAL_ARM_MODE := arm
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE := AACEncTest
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_ARM_MODE := arm
-LOCAL_SHARED_LIBRARIES := libvoAACEnc
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright \
+ libdl
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/ \
- $(LOCAL_PATH)/../../../Common \
- $(LOCAL_PATH)/../../../Include \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../common \
+ $(LOCAL_PATH)/../../common/include \
-LOCAL_CFLAGS := $(VO_CFLAGS)
-
include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
deleted file mode 100644
index 22c5dc1..0000000
--- a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-# target6
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v7
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= exe
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-# e.g. -DVISUALON, macro VISUALON defined for your module
-VOMM:= #ARMV5E
-
-
-
-# please specify the name of your module
-VOTARGET:= voAACEncTestv7
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=-ldl
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../../../../../Release/
-
-
-# please modify here to be sure to see the doit.mk
-include ../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
deleted file mode 100644
index 771a569..0000000
--- a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-# please list all objects needed by your target here
-OBJS:=AAC_E_SAMPLES.o cmnMemory.o
-
-# please list all directories that all source files relative with your module(.h .c .cpp) locate
-VOSRCDIR:=../ ../../../../include ../../../../Common
-
-
diff --git a/media/libstagefright/codecs/aacenc/Tools/doit.mk b/media/libstagefright/codecs/aacenc/Tools/doit.mk
deleted file mode 100644
index dea0b0a..0000000
--- a/media/libstagefright/codecs/aacenc/Tools/doit.mk
+++ /dev/null
@@ -1,133 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-
-VERBOSE:=@
-
-
-VOMT ?= lib
-
-ifeq ($(VOMT), lib)
-LIB_STATIC=$(VOTARGET).a
-LIB_DYNAMIC=$(VOTARGET).so
-endif
-
-ifeq ($(VOMT), exe)
-TARGET=$(VOTARGET)
-endif
-
-CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR))
-CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR))
-ifneq ($(VOTT), pc)
-ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR))
-endif
-
-LDFLAGS:=$(VOLDFLAGS)
-VOTEDEPS+=$(VODEPLIBS)
-VOTLDEPS+=$(VODEPLIBS)
-VOSTCLIBS ?=
-
-vpath %.c $(VOSRCDIR)
-vpath %.cpp $(VOSRCDIR)
-ifneq ($(VOTT), pc)
-vpath %.s $(VOSRCDIR)
-endif
-
-ifeq ($(VOTT), pc)
-BLTDIRS=$(VORELDIR)/Linux/static
-BLTDIRD=$(VORELDIR)/Linux/shared
-else
-BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT)
-BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT)
-endif
-
-
-.PRECIOUS: $(OBJDIR)/%.o
-
-ifeq ($(VOMT), lib)
-all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC)
-mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD)
-else
-all: mkdirs $(TARGET)
-mkdirs: $(OBJDIR)
-endif
-
-$(OBJDIR):
- @if test ! -d $@; then \
- mkdir -p $@; \
- fi;
-
-ifeq ($(VOMT), lib)
-$(BLTDIRS):
- @if test ! -d $@; then \
- mkdir -p $@; \
- fi;
-$(BLTDIRD):
- @if test ! -d $@; then \
- mkdir -p $@; \
- fi;
-endif
-
-
-ifeq ($(VOMT), lib)
-$(LIB_STATIC):$(OBJS)
- $(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS)
- $(RANLIB) $@
-ifneq ($(VODBG), yes)
- #$(STRIP) $@
-endif
-
-$(LIB_DYNAMIC):$(OBJS)
- $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS)
-ifneq ($(VODBG), yes)
- $(STRIP) $@
-endif
-
-else
-
-$(TARGET):$(OBJS)
- $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS)
-ifneq ($(VODBG), yes)
- $(STRIP) $@
-endif
-
-endif
-
-
-.SUFFIXES: .c .cpp .s .o
-.c.o:
- $(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $<
-#%.c:$(OBJDIR)/%.o
-# $(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $<
-.cpp.o:
- $(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $<
-ifneq ($(VOTT), pc)
-.s.o:
- $(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $<
-endif
-
-
-.PHONY: clean devel
-clean:
-ifeq ($(VOMT), lib)
- -rm -fr $(OBJDIR) .*.sw* $(VOTARGET).*
-else
- -rm -fr $(OBJDIR) .*.sw* $(VOTARGET)
-endif
-
-devel:
- cp -a $(LIB_STATIC) $(BLTDIRS)
- cp -a $(LIB_DYNAMIC) $(BLTDIRD)
-
diff --git a/media/libstagefright/codecs/aacenc/Tools/eclair.mk b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
deleted file mode 100644
index 1688361..0000000
--- a/media/libstagefright/codecs/aacenc/Tools/eclair.mk
+++ /dev/null
@@ -1,172 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-
-# special macro definitions for building
-VOPREDEF=-DLINUX -D_LINUX
-
-VOPRJ ?=
-VONJ ?= eclair
-VOTT ?= v6
-# control the version to release out
-# available: eva(evaluation), rel(release)
-VOVER=
-ifeq ($(VOVER), eva)
-VOPREDEF+=-D__VOVER_EVA__
-endif
-
-# for debug or not: yes for debug, any other for release
-VODBG?=ye
-
-# for detecting memory leak
-VODML=
-ifeq ($(VODML), yes)
-VOPREDEF+=-DDMEMLEAK
-endif
-
-VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__
-TCROOTPATH:=/opt/eclair
-GCCVER:=4.4.0
-TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER)
-CCTPRE:=$(TCPATH)/bin/arm-eabi-
-AS:=$(CCTPRE)as
-AR:=$(CCTPRE)ar
-NM:=$(CCTPRE)nm
-CC:=$(CCTPRE)gcc
-GG:=$(CCTPRE)g++
-LD:=$(CCTPRE)ld
-SIZE:=$(CCTPRE)size
-STRIP:=$(CCTPRE)strip
-RANLIB:=$(CCTPRE)ranlib
-OBJCOPY:=$(CCTPRE)objcopy
-OBJDUMP:=$(CCTPRE)objdump
-READELF:=$(CCTPRE)readelf
-STRINGS:=$(CCTPRE)strings
-
-# target product dependcy
-# available: dream, generic
-VOTP:=sapphire-open
-CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib
-CCTINC:=-I$(TCROOTPATH)/system/core/include \
- -I$(TCROOTPATH)/hardware/libhardware/include \
- -I$(TCROOTPATH)/hardware/ril/include \
- -I$(TCROOTPATH)/hardware/libhardware_legacy/include \
- -I$(TCROOTPATH)/dalvik/libnativehelper/include \
- -I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \
- -I$(TCROOTPATH)/frameworks/base/include \
- -I$(TCROOTPATH)/frameworks/base/core/jni \
- -I$(TCROOTPATH)/frameworks/base/libs/audioflinger \
- -I$(TCROOTPATH)/external/skia/include \
- -I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \
- -I$(TCROOTPATH)/bionic/libc/arch-arm/include \
- -I$(TCROOTPATH)/bionic/libc/include \
- -I$(TCROOTPATH)/bionic/libstdc++/include \
- -I$(TCROOTPATH)/bionic/libc/kernel/common \
- -I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \
- -I$(TCROOTPATH)/bionic/libm/include \
- -I$(TCROOTPATH)/bionic/libm/include/arm \
- -I$(TCROOTPATH)/bionic/libthread_db/include \
- -I$(TCROOTPATH)/bionic/libm/arm \
- -I$(TCROOTPATH)/bionic/libm \
- -I$(TCROOTPATH)/frameworks/base/include/android_runtime
- #-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates
-
-CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops
-#-fwide-exec-charset=charset=UTF-32
-
-# for target exe
-TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB)
-
-VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm
-
-# for target lib
-TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a
-
-VOTLDEPS:=-lm -lc
-
-
-ifeq ($(VOTT), v4)
-VOCFLAGS:=-mtune=arm9tdmi -march=armv4t
-VOASFLAGS:=-march=armv4t -mfpu=softfpa
-endif
-
-ifeq ($(VOTT), v5)
-VOCFLAGS:=-march=armv5te
-VOASFLAGS:=-march=armv5te -mfpu=vfp
-endif
-
-ifeq ($(VOTT), v5x)
-VOCFLAGS:=-march=armv5te -mtune=xscale
-VOASFLAGS:=-march=armv5te -mfpu=vfp
-endif
-
-ifeq ($(VOTT), v6)
-#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s
-#VOASFLAGS:=-march=armv6
-VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls
-VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant
-endif
-
-#
-# global link options
-VOLDFLAGS:=-Wl,-x,-X,--as-needed
-
-
-ifeq ($(VOTT), v7)
-VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
-VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp
-VOLDFLAGS+=-Wl,--fix-cortex-a8
-endif
-
-#global compiling options for ARM target
-ifneq ($(VOTT), pc)
-VOASFLAGS+=--strip-local-absolute -R
-endif
-
-
-ifeq ($(VODBG), yes)
-VOCFLAGS+=-D_DEBUG -g
-else
-VOCFLAGS+=-DNDEBUG -O3
-endif
-
-VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear -mthumb -nostdinc -dD -fprefetch-loop-arrays
-
-
-ifneq ($(VOTT), pc)
-VOCFLAGS+=$(CCTCFLAGS) $(CCTINC)
-VOCPPFLAGS:=-fno-rtti $(VOCFLAGS)
-
-ifeq ($(VOMT), exe)
-VOLDFLAGS+=$(TELDFLAGS)
-endif
-
-ifeq ($(VOMT), lib)
-VOLDFLAGS+=$(TLLDFLAGS)
-endif
-else
-VOCPPFLAGS:=$(VOCFLAGS)
-ifeq ($(VOMT), lib)
-VOLDFLAGS+=-shared
-endif
-endif
-
-ifeq ($(VODBG), yes)
-#VOLDFLAGS:=
-endif
-
-# where to place object files
-OBJDIR=obj
-
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
deleted file mode 100644
index b4f63af..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-# target6
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v5
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= lib
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-# e.g. -DVISUALON, macro VISUALON defined for your module
-VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM
-
-
-
-# please specify the name of your module
-VOTARGET:=libvoAACEncv5
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=#-ldl -lstdc++
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../../../../../../Release
-
-
-# please modify here to be sure to see the doit.mk
-include ../../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
deleted file mode 100644
index cdce2c1..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-# target6
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v7
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= lib
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-# e.g. -DVISUALON, macro VISUALON defined for your module
-VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
-
-
-
-# please specify the name of your module
-VOTARGET:=libvoAACEncv7
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=#-ldl -lstdc++
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../../../../../../Release
-
-
-# please modify here to be sure to see the doit.mk
-include ../../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/makefile b/media/libstagefright/codecs/aacenc/build/eclair/makefile
deleted file mode 100644
index 6bb3c13..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-# Just acting as Father Makefile of Modules
-# please keep the name 'makefile' unchanged
-
-# Module Subdirs
-VOMSD:=$(dir $(shell find . -name 'Makefile'))
-
-all:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir; \
- done
-
-.PHONY:clean devel
-clean:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir clean; \
- done
-
-devel:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir devel; \
- done
diff --git a/media/libstagefright/codecs/aacenc/build/ms.mk b/media/libstagefright/codecs/aacenc/build/ms.mk
deleted file mode 100644
index b67efbc..0000000
--- a/media/libstagefright/codecs/aacenc/build/ms.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** 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.
-#*/
-
-
-# please list all objects needed by your target here
-OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \
- band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \
- dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \
- pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \
- spreading.o stat_bits.o tns.o transform.o
-
-# please list all directories that all source files relative with your module(.h .c .cpp) locate
-VOSRCDIR:=../../../src \
- ../../../inc \
- ../../../basic_op\
- ../../../../../Include
-
-ifeq ($(VOTT), v5)
-OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
- PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o
-VOSRCDIR+= ../../../src/asm/ARMV5E/
-endif
-
-ifeq ($(VOTT), v7)
-OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
- PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o
-VOSRCDIR+= ../../../src/asm/ARMV5E/
-VOSRCDIR+= ../../../src/asm/ARMV7/
-endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index fb300da..a11d46b 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMRNBDecoder"
+#include <utils/Log.h>
+
#include "AMRNBDecoder.h"
#include "gsmamr_dec.h"
@@ -154,18 +158,24 @@ status_t AMRNBDecoder::read(
const uint8_t *inputPtr =
(const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
- size_t numBytesRead =
+ int32_t numBytesRead =
AMRDecode(mState,
(Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
(UWord8 *)&inputPtr[1],
static_cast<int16_t *>(buffer->data()),
MIME_IETF);
+ if (numBytesRead == -1 ) {
+ LOGE("PV AMR decoder AMRDecode() call failed");
+ buffer->release();
+ buffer = NULL;
+ return ERROR_MALFORMED;
+ }
++numBytesRead; // Include the frame type header byte.
buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
- if (numBytesRead > mInputBuffer->range_length()) {
+ if (static_cast<size_t>(numBytesRead) > mInputBuffer->range_length()) {
// This is bad, should never have happened, but did. Abort now.
buffer->release();
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 4293287..5179380 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
-LOCAL_PRELINK_MODULE := false
+
LOCAL_SRC_FILES := \
AMRWBEncoder.cpp \
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
index 792d3cc..5e71a5b 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -129,7 +129,7 @@ int encode(
useData.memData = (VO_PTR)(&moper);
#ifdef LINUX
- handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW);
+ handle = dlopen("libstagefright.so", RTLD_NOW);
if(handle == 0)
{
printf("open dll error......");
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
index 7edb166..85ddceb 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
@@ -1,26 +1,26 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := AMRWB_E_SAMPLE.c
-
-LOCAL_SRC_FILES += \
- ../../../Common/cmnMemory.c
+LOCAL_SRC_FILES := \
+ AMRWB_E_SAMPLE.c \
+ ../../common/cmnMemory.c
-LOCAL_MODULE := TestvoAMRWBEnc
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := AMRWBEncTest
LOCAL_ARM_MODE := arm
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_CFLAGS := $(VO_CFLAGS)
-LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright \
+ libdl
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/ \
- $(LOCAL_PATH)/../../../Common \
- $(LOCAL_PATH)/../../../Include \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../common \
+ $(LOCAL_PATH)/../../common/include
-LOCAL_CFLAGS := $(VO_CFLAGS)
-
include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
deleted file mode 100644
index 55b876a..0000000
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-
-# target6
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v6
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= exe
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-# e.g. -DVISUALON, macro VISUALON defined for your module
-VOMM:= #ARMV5E
-
-
-
-# please specify the name of your module
-VOTARGET:= voAMRWBEnc_Test
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=-ldl
-
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../
-
-
-# please modify here to be sure to see the doit.mk
-include ../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
deleted file mode 100644
index 74e8913..0000000
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-# please list all objects needed by your target here
-OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o
-
-# please list all directories that all source files relative with your module(.h .c .cpp) locate
-VOSRCDIR:=../ \
- ../../../../Common \
- ../../../../Include
-
-
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
deleted file mode 100644
index 58fda29..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-
-# target type
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v5
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= lib
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-ifeq ($(VOTT), v5)
-VOMM:=-DARM -DASM_OPT
-endif
-
-# please specify the name of your module
-VOTARGET:= libvoAMRWBEncv5
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=-ldl -lstdc++ -lcutils
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../../../../../../Release
-
-# please modify here to be sure to see the doit.mk
-include ../../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
deleted file mode 100644
index 5686411..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-
-# target type
-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
-VOTT:= v7
-
-
-# module type
-# please specify the type of your module: lib or exe
-VOMT:= lib
-
-
-# module macros
-# please append the additional macro definitions here for your module if necessary.
-ifeq ($(VOTT), v7)
-VOMM:=-DARM -DARMV7 -DASM_OPT
-endif
-
-# please specify the name of your module
-VOTARGET:= libvoAMRWBEncv7
-
-
-# please modify here to be sure to see the g1.mk
-include ../../../../../Tools/eclair.mk
-
-# dependent libraries.
-VODEPLIBS:=-ldl -lstdc++ -lcutils
-
-# module source
-# please modify here to be sure to see the ms.mk which specifies all source info of your module
-include ../ms.mk
-
-
-# please specify where is the voRelease on your PC, relative path is suggested
-VORELDIR:=../../../../../../Release
-
-# please modify here to be sure to see the doit.mk
-include ../../../../../Tools/doit.mk
-
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
deleted file mode 100644
index 3473a1a..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-# Just acting as Father Makefile of Modules
-# please keep the name 'makefile' unchanged
-
-# Module Subdirs
-VOMSD:=$(dir $(shell find . -name 'Makefile'))
-
-all:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir; \
- done
-
-.PHONY:clean devel
-clean:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir clean; \
- done
-
-devel:
- for dir in $(VOMSD); \
- do \
- $(MAKE) -C $$dir devel; \
- done
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
deleted file mode 100644
index bd6620c..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** 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.
-# */
-# please list all directories that all source files relative with your module(.h .c .cpp) locate
-VOSRCDIR:=../../../inc \
- ../../../src \
- ../../../../../Include
-
-# please list all objects needed by your target here
-OBJS:= autocorr.o az_isp.o bits.o c2t64fx.o c4t64fx.o convolve.o cor_h_x.o decim54.o \
- deemph.o dtx.o g_pitch.o gpclip.o homing.o hp400.o hp50.o hp6k.o hp_wsp.o \
- int_lpc.o isp_az.o isp_isf.o lag_wind.o levinson.o log2.o lp_dec2.o math_op.o mem_align.o \
- oper_32b.o p_med_ol.o pit_shrp.o pitch_f4.o pred_lt4.o preemph.o q_gain2.o q_pulse.o \
- qisf_ns.o qpisf_2s.o random.o residu.o scale.o stream.o syn_filt.o updt_tar.o util.o \
- voAMRWBEnc.o voicefac.o wb_vad.o weight_a.o
-
-
-ifeq ($(VOTT), v5)
-OBJS += cor_h_vec_opt.o Deemph_32_opt.o Dot_p_opt.o Filt_6k_7k_opt.o residu_asm_opt.o \
- scale_sig_opt.o Syn_filt_32_opt.o syn_filt_opt.o pred_lt4_1_opt.o convolve_opt.o \
- Norm_Corr_opt.o
-VOSRCDIR+= ../../../src/asm/ARMV5E
-endif
-
-ifeq ($(VOTT), v7)
-OBJS+= cor_h_vec_neon.o Deemph_32_neon.o Dot_p_neon.o Filt_6k_7k_neon.o residu_asm_neon.o \
- scale_sig_neon.o Syn_filt_32_neon.o syn_filt_neon.o pred_lt4_1_neon.o convolve_neon.o \
- Norm_Corr_neon.o
-VOSRCDIR+= ../../../src/asm/ARMV7
-endif
-
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 5bbba35..490129f 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -534,7 +534,8 @@ status_t AVCDecoder::read(
default:
{
LOGE("Should not be here, unknown nalType %d", nalType);
- CHECK(!"Should not be here");
+
+ err = ERROR_MALFORMED;
break;
}
}
diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk
index fffb2ad..af8795a 100644
--- a/media/libstagefright/codecs/common/Android.mk
+++ b/media/libstagefright/codecs/common/Android.mk
@@ -1,7 +1,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PRELINK_MODULE := false
+
LOCAL_SRC_FILES := cmnMemory.c
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index 59dd740..0ba42ff 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MP3Decoder"
+
#include "MP3Decoder.h"
#include "include/pvmp3decoder_api.h"
@@ -175,7 +178,12 @@ status_t MP3Decoder::read(
!= NO_DECODING_ERROR) {
LOGV("mp3 decoder returned error %d", decoderErr);
- if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) {
+ if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR ||
+ mConfig->outputFrameSize == 0) {
+
+ if (mConfig->outputFrameSize == 0) {
+ LOGE("Output frame size is 0");
+ }
buffer->release();
buffer = NULL;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 31afc43..3b13476 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -108,7 +108,7 @@ SoftwareRenderer::~SoftwareRenderer() {
void SoftwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
- android_native_buffer_t *buf;
+ ANativeWindowBuffer *buf;
int err;
if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) {
LOGW("Surface::dequeueBuffer returned error %d", err);
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index b7087f8..a5b316d 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -33,18 +33,30 @@ ALooperRoster gLooperRoster;
struct ALooper::LooperThread : public Thread {
LooperThread(ALooper *looper, bool canCallJava)
: Thread(canCallJava),
- mLooper(looper) {
+ mLooper(looper),
+ mThreadId(NULL) {
+ }
+
+ virtual status_t readyToRun() {
+ mThreadId = androidGetThreadId();
+
+ return Thread::readyToRun();
}
virtual bool threadLoop() {
return mLooper->loop();
}
+ bool isCurrentThread() const {
+ return mThreadId == androidGetThreadId();
+ }
+
protected:
virtual ~LooperThread() {}
private:
ALooper *mLooper;
+ android_thread_id_t mThreadId;
DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
};
@@ -136,7 +148,9 @@ status_t ALooper::stop() {
mQueueChangedCondition.signal();
- if (!runningLocally) {
+ if (!runningLocally && !thread->isCurrentThread()) {
+ // If not running locally and this thread _is_ the looper thread,
+ // the loop() function will return and never be called again.
thread->requestExitAndWait();
}
@@ -197,6 +211,11 @@ bool ALooper::loop() {
gLooperRoster.deliverMessage(event.mMessage);
+ // NOTE: It's important to note that at this point our "ALooper" object
+ // may no longer exist (its final reference may have gone away while
+ // delivering the message). We have made sure, however, that loop()
+ // won't be called again.
+
return true;
}
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 4e07f6f..d5025a1 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -25,6 +25,6 @@ LOCAL_CFLAGS += -Wno-multichar
LOCAL_MODULE:= libstagefright_foundation
-LOCAL_PRELINK_MODULE:= false
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index f0cd6a0..012d9ad 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -23,7 +23,7 @@
#include "LiveDataSource.h"
#include "include/M3UParser.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
#include <cutils/properties.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -45,9 +45,9 @@ LiveSession::LiveSession(uint32_t flags)
: mFlags(flags),
mDataSource(new LiveDataSource),
mHTTPDataSource(
- new NuHTTPDataSource(
+ HTTPBase::Create(
(mFlags & kFlagIncognito)
- ? NuHTTPDataSource::kFlagIncognito
+ ? HTTPBase::kFlagIncognito
: 0)),
mPrevBandwidthIndex(-1),
mLastPlaylistFetchTimeUs(-1),
@@ -67,9 +67,17 @@ sp<DataSource> LiveSession::getDataSource() {
return mDataSource;
}
-void LiveSession::connect(const char *url) {
+void LiveSession::connect(
+ const char *url, const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatConnect, id());
msg->setString("url", url);
+
+ if (headers != NULL) {
+ msg->setPointer(
+ "headers",
+ new KeyedVector<String8, String8>(*headers));
+ }
+
msg->post();
}
@@ -144,6 +152,16 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
AString url;
CHECK(msg->findString("url", &url));
+ KeyedVector<String8, String8> *headers = NULL;
+ if (!msg->findPointer("headers", (void **)&headers)) {
+ mExtraHeaders.clear();
+ } else {
+ mExtraHeaders = *headers;
+
+ delete headers;
+ headers = NULL;
+ }
+
if (!(mFlags & kFlagIncognito)) {
LOGI("onConnect '%s'", url.c_str());
} else {
@@ -210,7 +228,8 @@ status_t LiveSession::fetchFile(const char *url, sp<ABuffer> *out) {
}
}
- status_t err = mHTTPDataSource->connect(url);
+ status_t err = mHTTPDataSource->connect(
+ url, mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
if (err != OK) {
return err;
@@ -625,7 +644,12 @@ status_t LiveSession::decryptBuffer(
} else {
key = new ABuffer(16);
- sp<NuHTTPDataSource> keySource = new NuHTTPDataSource;
+ sp<HTTPBase> keySource =
+ HTTPBase::Create(
+ (mFlags & kFlagIncognito)
+ ? HTTPBase::kFlagIncognito
+ : 0);
+
status_t err = keySource->connect(keyURI.c_str());
if (err == OK) {
diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
new file mode 100644
index 0000000..375a94d
--- /dev/null
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 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 AVI_EXTRACTOR_H_
+
+#define AVI_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AVIExtractor : public MediaExtractor {
+ AVIExtractor(const sp<DataSource> &dataSource);
+
+ virtual size_t countTracks();
+
+ virtual sp<MediaSource> getTrack(size_t index);
+
+ virtual sp<MetaData> getTrackMetaData(
+ size_t index, uint32_t flags);
+
+ virtual sp<MetaData> getMetaData();
+
+protected:
+ virtual ~AVIExtractor();
+
+private:
+ struct AVISource;
+
+ struct SampleInfo {
+ uint32_t mOffset;
+ bool mIsKey;
+ };
+
+ struct Track {
+ sp<MetaData> mMeta;
+ Vector<SampleInfo> mSamples;
+ uint32_t mRate;
+ uint32_t mScale;
+
+ enum Kind {
+ AUDIO,
+ VIDEO,
+ OTHER
+
+ } mKind;
+
+ size_t mNumSyncSamples;
+ size_t mThumbnailSampleSize;
+ ssize_t mThumbnailSampleIndex;
+ size_t mMaxSampleSize;
+ };
+
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ Vector<Track> mTracks;
+
+ off64_t mMovieOffset;
+ bool mFoundIndex;
+ bool mOffsetsAreAbsolute;
+
+ ssize_t parseChunk(off64_t offset, off64_t size, int depth = 0);
+ status_t parseStreamHeader(off64_t offset, size_t size);
+ status_t parseStreamFormat(off64_t offset, size_t size);
+ status_t parseIndex(off64_t offset, size_t size);
+
+ status_t parseHeaders();
+
+ status_t getSampleInfo(
+ size_t trackIndex, size_t sampleIndex,
+ off64_t *offset, size_t *size, bool *isKey);
+
+ status_t getSampleIndexAtTime(
+ size_t trackIndex,
+ int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+ size_t *sampleIndex) const;
+
+ status_t addMPEG4CodecSpecificData(size_t trackIndex);
+
+ static bool IsCorrectChunkType(
+ ssize_t trackIndex, Track::Kind kind, uint32_t chunkType);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AVIExtractor);
+};
+
+class String8;
+struct AMessage;
+
+bool SniffAVI(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // AVI_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 4e6f75c..fd3ddf7 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -18,7 +18,7 @@
#define AWESOME_PLAYER_H_
-#include "NuHTTPDataSource.h"
+#include "HTTPBase.h"
#include "TimedEventQueue.h"
#include <media/MediaPlayerInterface.h>
@@ -44,6 +44,8 @@ struct ARTSPController;
class DrmManagerClinet;
class DecryptHandle;
+class TimedTextPlayer;
+
struct AwesomeRenderer : public RefBase {
AwesomeRenderer() {}
@@ -88,44 +90,52 @@ struct AwesomePlayer {
status_t getDuration(int64_t *durationUs);
status_t getPosition(int64_t *positionUs);
+ status_t setParameter(int key, const Parcel &request);
+ status_t getParameter(int key, Parcel *reply);
+
status_t seekTo(int64_t timeUs);
// This is a mask of MediaExtractor::Flags.
uint32_t flags() const;
- void postAudioEOS();
+ void postAudioEOS(int64_t delayUs = 0ll);
void postAudioSeekComplete();
+ status_t setTimedTextTrackIndex(int32_t index);
+
private:
friend struct AwesomeEvent;
friend struct PreviewPlayer;
enum {
- PLAYING = 1,
- LOOPING = 2,
- FIRST_FRAME = 4,
- PREPARING = 8,
- PREPARED = 16,
- AT_EOS = 32,
- PREPARE_CANCELLED = 64,
- CACHE_UNDERRUN = 128,
- AUDIO_AT_EOS = 256,
- VIDEO_AT_EOS = 512,
- AUTO_LOOPING = 1024,
+ PLAYING = 0x01,
+ LOOPING = 0x02,
+ FIRST_FRAME = 0x04,
+ PREPARING = 0x08,
+ PREPARED = 0x10,
+ AT_EOS = 0x20,
+ PREPARE_CANCELLED = 0x40,
+ CACHE_UNDERRUN = 0x80,
+ AUDIO_AT_EOS = 0x0100,
+ VIDEO_AT_EOS = 0x0200,
+ AUTO_LOOPING = 0x0400,
// We are basically done preparing but are currently buffering
// sufficient data to begin playback and finish the preparation phase
// for good.
- PREPARING_CONNECTED = 2048,
+ PREPARING_CONNECTED = 0x0800,
// We're triggering a single video event to display the first frame
// after the seekpoint.
- SEEK_PREVIEW = 4096,
+ SEEK_PREVIEW = 0x1000,
+
+ AUDIO_RUNNING = 0x2000,
+ AUDIOPLAYER_STARTED = 0x4000,
- AUDIO_RUNNING = 8192,
- AUDIOPLAYER_STARTED = 16384,
+ INCOGNITO = 0x8000,
- INCOGNITO = 32768,
+ TEXT_RUNNING = 0x10000,
+ TEXTPLAYER_STARTED = 0x20000,
};
mutable Mutex mLock;
@@ -163,7 +173,6 @@ private:
uint32_t mFlags;
uint32_t mExtractorFlags;
- uint32_t mSinceLastDropped;
int64_t mTimeSourceDeltaUs;
int64_t mVideoTimeUs;
@@ -203,13 +212,13 @@ private:
void postVideoEvent_l(int64_t delayUs = -1);
void postBufferingEvent_l();
void postStreamDoneEvent_l(status_t status);
- void postCheckAudioStatusEvent_l();
+ void postCheckAudioStatusEvent_l(int64_t delayUs);
void postVideoLagEvent_l();
status_t play_l();
MediaBuffer *mVideoBuffer;
- sp<NuHTTPDataSource> mConnectingDataSource;
+ sp<HTTPBase> mConnectingDataSource;
sp<NuCachedSource2> mCachedSource;
sp<ALooper> mLooper;
@@ -217,7 +226,10 @@ private:
sp<ARTSPController> mConnectingRTSPController;
DrmManagerClient *mDrmManagerClient;
- DecryptHandle *mDecryptHandle;
+ sp<DecryptHandle> mDecryptHandle;
+
+ int64_t mLastVideoTimeUs;
+ TimedTextPlayer *mTextPlayer;
status_t setDataSource_l(
const char *uri,
@@ -240,6 +252,8 @@ private:
void setVideoSource(sp<MediaSource> source);
status_t initVideoDecoder(uint32_t flags = 0);
+ void addTextSource(sp<MediaSource> source);
+
void onStreamDone();
void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0);
@@ -268,6 +282,9 @@ private:
status_t startAudioPlayer_l();
+ void shutdownVideoDecoder_l();
+ void setNativeWindow_l(const sp<ANativeWindow> &native);
+
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
};
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
new file mode 100644
index 0000000..0e2927d
--- /dev/null
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 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 CHROME_HTTP_DATA_SOURCE_H_
+
+#define CHROME_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/foundation/AString.h>
+#include <utils/threads.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+struct SfDelegate;
+
+struct ChromiumHTTPDataSource : public HTTPBase {
+ ChromiumHTTPDataSource(uint32_t flags = 0);
+
+ virtual status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL,
+ off64_t offset = 0);
+
+ virtual void disconnect();
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ virtual status_t getSize(off64_t *size);
+ virtual uint32_t flags();
+
+ virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+ virtual sp<DecryptHandle> DrmInitialization();
+
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+
+ virtual String8 getUri();
+
+ virtual String8 getMIMEType() const;
+
+protected:
+ virtual ~ChromiumHTTPDataSource();
+
+private:
+ friend struct SfDelegate;
+
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ READING,
+ DISCONNECTING
+ };
+
+ struct BandwidthEntry {
+ int64_t mDelayUs;
+ size_t mNumBytes;
+ };
+
+ const uint32_t mFlags;
+
+ mutable Mutex mLock;
+ Condition mCondition;
+
+ State mState;
+
+ SfDelegate *mDelegate;
+
+ AString mURI;
+ KeyedVector<String8, String8> mHeaders;
+
+ off64_t mCurrentOffset;
+
+ // Any connection error or the result of a read operation
+ // (for the lattter this is the number of bytes read, if successful).
+ ssize_t mIOResult;
+
+ int64_t mContentSize;
+
+ String8 mContentType;
+
+ List<BandwidthEntry> mBandwidthHistory;
+ size_t mNumBandwidthHistoryItems;
+ int64_t mTotalTransferTimeUs;
+ size_t mTotalTransferBytes;
+
+ sp<DecryptHandle> mDecryptHandle;
+ DrmManagerClient *mDrmManagerClient;
+
+ void disconnect_l();
+
+ status_t connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ static void InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size);
+
+ void initiateRead(void *data, size_t size);
+
+ void onConnectionEstablished(
+ int64_t contentSize, const char *contentType);
+
+ void onConnectionFailed(status_t err);
+ void onReadCompleted(ssize_t size);
+ void onDisconnectComplete();
+
+ void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
+
+ void clearDRMState_l();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource);
+};
+
+} // namespace android
+
+#endif // CHROME_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index 9881cc1..b4e4afb 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -45,7 +45,7 @@ private:
sp<DataSource> mDataSource;
sp<MediaExtractor> mOriginalExtractor;
- DecryptHandle* mDecryptHandle;
+ sp<DecryptHandle> mDecryptHandle;
DrmManagerClient* mDrmManagerClient;
DRMExtractor(const DRMExtractor &);
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
new file mode 100644
index 0000000..6cec390
--- /dev/null
+++ b/media/libstagefright/include/HTTPBase.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 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 HTTP_BASE_H_
+
+#define HTTP_BASE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+struct HTTPBase : public DataSource {
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1
+ };
+
+ HTTPBase();
+
+ virtual status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL,
+ off64_t offset = 0) = 0;
+
+ virtual void disconnect() = 0;
+
+ // Returns true if bandwidth could successfully be estimated,
+ // false otherwise.
+ virtual bool estimateBandwidth(int32_t *bandwidth_bps) = 0;
+
+ static sp<HTTPBase> Create(uint32_t flags = 0);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
+};
+
+} // namespace android
+
+#endif // HTTP_BASE_H_
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 3fe5d4e..99abe64 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -20,13 +20,15 @@
#include <media/stagefright/foundation/AHandler.h>
+#include <utils/String8.h>
+
namespace android {
struct ABuffer;
struct DataSource;
struct LiveDataSource;
struct M3UParser;
-struct NuHTTPDataSource;
+struct HTTPBase;
struct LiveSession : public AHandler {
enum Flags {
@@ -37,7 +39,10 @@ struct LiveSession : public AHandler {
sp<DataSource> getDataSource();
- void connect(const char *url);
+ void connect(
+ const char *url,
+ const KeyedVector<String8, String8> *headers = NULL);
+
void disconnect();
// Blocks until seek is complete.
@@ -75,9 +80,11 @@ private:
sp<LiveDataSource> mDataSource;
- sp<NuHTTPDataSource> mHTTPDataSource;
+ sp<HTTPBase> mHTTPDataSource;
AString mMasterURL;
+ KeyedVector<String8, String8> mExtraHeaders;
+
Vector<BandwidthItem> mBandwidthItems;
KeyedVector<AString, sp<ABuffer> > mAESKeyForURI;
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index ef71b8f..cf1146b 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -42,7 +42,7 @@ public:
static bool get_mp3_frame_size(
uint32_t header, size_t *frame_size,
int *out_sampling_rate = NULL, int *out_channels = NULL,
- int *out_bitrate = NULL);
+ int *out_bitrate = NULL, int *out_num_samples = NULL);
private:
status_t mInitCheck;
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 04e8a6a..3bd4c7e 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -57,7 +57,7 @@ private:
};
sp<DataSource> mDataSource;
- bool mHaveMetadata;
+ status_t mInitCheck;
bool mHasVideo;
Track *mFirstTrack, *mLastTrack;
@@ -90,6 +90,8 @@ private:
status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
+ Track *findTrackByMimePrefix(const char *mimePrefix);
+
MPEG4Extractor(const MPEG4Extractor &);
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 022804c..ed3e265 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -37,9 +37,12 @@ struct NuCachedSource2 : public DataSource {
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- virtual DecryptHandle* DrmInitialization();
- virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+ virtual sp<DecryptHandle> DrmInitialization();
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
virtual String8 getUri();
+
+ virtual String8 getMIMEType() const;
+
////////////////////////////////////////////////////////////////////////////
size_t cachedSize();
@@ -93,7 +96,9 @@ private:
status_t seekInternal_l(off64_t offset);
size_t approxDataRemaining_l(status_t *finalStatus);
- void restartPrefetcherIfNecessary_l(bool ignoreLowWaterThreshold = false);
+
+ void restartPrefetcherIfNecessary_l(
+ bool ignoreLowWaterThreshold = false, bool force = false);
DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
};
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 0d68234..2ab1f19 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -18,28 +18,24 @@
#define NU_HTTP_DATA_SOURCE_H_
-#include <media/stagefright/DataSource.h>
#include <utils/List.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include "HTTPStream.h"
+#include "include/HTTPBase.h"
namespace android {
-struct NuHTTPDataSource : public DataSource {
- enum Flags {
- // Don't log any URLs.
- kFlagIncognito = 1
- };
+struct NuHTTPDataSource : public HTTPBase {
NuHTTPDataSource(uint32_t flags = 0);
- status_t connect(
+ virtual status_t connect(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL,
off64_t offset = 0);
- void disconnect();
+ virtual void disconnect();
virtual status_t initCheck() const;
@@ -49,12 +45,14 @@ struct NuHTTPDataSource : public DataSource {
// Returns true if bandwidth could successfully be estimated,
// false otherwise.
- bool estimateBandwidth(int32_t *bandwidth_bps);
+ virtual bool estimateBandwidth(int32_t *bandwidth_bps);
- virtual DecryptHandle* DrmInitialization();
- virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+ virtual sp<DecryptHandle> DrmInitialization();
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
virtual String8 getUri();
+ virtual String8 getMIMEType() const;
+
protected:
virtual ~NuHTTPDataSource();
@@ -89,6 +87,8 @@ private:
bool mContentLengthValid;
bool mHasChunkedTransferEncoding;
+ String8 mContentType;
+
// The number of data bytes in the current chunk before any subsequent
// chunk header (or -1 if no more chunks).
ssize_t mChunkDataBytesLeft;
@@ -97,9 +97,8 @@ private:
size_t mNumBandwidthHistoryItems;
int64_t mTotalTransferTimeUs;
size_t mTotalTransferBytes;
- int64_t mPrevBandwidthMeasureTimeUs;
- DecryptHandle *mDecryptHandle;
+ sp<DecryptHandle> mDecryptHandle;
DrmManagerClient *mDrmManagerClient;
status_t connect(
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 2f95de9..f44e0a2 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -63,7 +63,7 @@ public:
uint32_t sampleIndex,
off64_t *offset,
size_t *size,
- uint32_t *decodingTime,
+ uint32_t *compositionTime,
bool *isSyncSample = NULL);
enum {
@@ -107,6 +107,12 @@ private:
uint32_t mTimeToSampleCount;
uint32_t *mTimeToSample;
+ struct SampleTimeEntry {
+ uint32_t mSampleIndex;
+ uint32_t mCompositionTime;
+ };
+ SampleTimeEntry *mSampleTimeEntries;
+
uint32_t *mCompositionTimeDeltaEntries;
size_t mNumCompositionTimeDeltaEntries;
@@ -130,6 +136,10 @@ private:
uint32_t getCompositionTimeOffset(uint32_t sampleIndex) const;
+ static int CompareIncreasingTime(const void *, const void *);
+
+ void buildSampleEntriesTable();
+
SampleTable(const SampleTable &);
SampleTable &operator=(const SampleTable &);
};
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index 07b1ec8..b02ed0e 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -32,7 +32,10 @@ struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface {
StagefrightMetadataRetriever();
virtual ~StagefrightMetadataRetriever();
- virtual status_t setDataSource(const char *url);
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers);
+
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option);
diff --git a/media/libstagefright/include/TimedTextPlayer.h b/media/libstagefright/include/TimedTextPlayer.h
new file mode 100644
index 0000000..ac41b4f
--- /dev/null
+++ b/media/libstagefright/include/TimedTextPlayer.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 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 TIMEDTEXT_PLAYER_H_
+
+#define TIMEDTEXT_PLAYER_H_
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include "include/TimedEventQueue.h"
+
+namespace android {
+
+class MediaSource;
+class AwesomePlayer;
+class MediaBuffer;
+
+class TimedTextPlayer {
+public:
+ TimedTextPlayer(AwesomePlayer *observer,
+ const wp<MediaPlayerBase> &listener,
+ TimedEventQueue *queue);
+
+ virtual ~TimedTextPlayer();
+
+ // index: the index of the text track which will
+ // be turned on
+ status_t start(uint8_t index);
+
+ void pause();
+
+ void resume();
+
+ status_t seekTo(int64_t time_us);
+
+ void addTextSource(sp<MediaSource> source);
+
+ status_t setTimedTextTrackIndex(int32_t index);
+
+private:
+ Mutex mLock;
+
+ sp<MediaSource> mSource;
+
+ bool mSeeking;
+ int64_t mSeekTimeUs;
+
+ bool mStarted;
+
+ sp<TimedEventQueue::Event> mTextEvent;
+ bool mTextEventPending;
+
+ TimedEventQueue *mQueue;
+
+ wp<MediaPlayerBase> mListener;
+ AwesomePlayer *mObserver;
+
+ MediaBuffer *mTextBuffer;
+ Parcel mData;
+
+ Vector<sp<MediaSource> > mTextTrackVector;
+
+ void reset();
+
+ void onTextEvent();
+ void postTextEvent(int64_t delayUs = -1);
+ void cancelTextEvent();
+
+ void notifyListener(
+ int msg, const void *data = NULL, size_t size = 0);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextPlayer);
+};
+
+} // namespace android
+
+#endif // TIMEDTEXT_PLAYER_H_
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 733de92..e1b9991 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -60,7 +60,10 @@ struct DataSourceReader : public mkvparser::IMkvReader {
virtual int Length(long long* total, long long* available) {
off64_t size;
if (mSource->getSize(&size) != OK) {
- return -1;
+ *total = -1;
+ *available = (long long)((1ull << 63) - 1);
+
+ return 0;
}
if (total) {
@@ -84,7 +87,7 @@ private:
////////////////////////////////////////////////////////////////////////////////
struct BlockIterator {
- BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
+ BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum);
bool eos() const;
@@ -96,11 +99,14 @@ struct BlockIterator {
int64_t blockTimeUs() const;
private:
- mkvparser::Segment *mSegment;
+ MatroskaExtractor *mExtractor;
unsigned long mTrackNum;
- mkvparser::Cluster *mCluster;
+ const mkvparser::Cluster *mCluster;
const mkvparser::BlockEntry *mBlockEntry;
+ long mBlockEntryIndex;
+
+ void advance_l();
BlockIterator(const BlockIterator &);
BlockIterator &operator=(const BlockIterator &);
@@ -150,7 +156,7 @@ MatroskaSource::MatroskaSource(
: mExtractor(extractor),
mTrackIndex(index),
mType(OTHER),
- mBlockIter(mExtractor->mSegment,
+ mBlockIter(mExtractor.get(),
mExtractor->mTracks.itemAt(index).mTrackNum),
mNALSizeLen(0) {
sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
@@ -199,11 +205,12 @@ sp<MetaData> MatroskaSource::getFormat() {
////////////////////////////////////////////////////////////////////////////////
BlockIterator::BlockIterator(
- mkvparser::Segment *segment, unsigned long trackNum)
- : mSegment(segment),
+ MatroskaExtractor *extractor, unsigned long trackNum)
+ : mExtractor(extractor),
mTrackNum(trackNum),
mCluster(NULL),
- mBlockEntry(NULL) {
+ mBlockEntry(NULL),
+ mBlockEntryIndex(0) {
reset();
}
@@ -212,45 +219,100 @@ bool BlockIterator::eos() const {
}
void BlockIterator::advance() {
- while (!eos()) {
- if (mBlockEntry != NULL) {
- mBlockEntry = mCluster->GetNext(mBlockEntry);
- } else if (mCluster != NULL) {
- mCluster = mSegment->GetNext(mCluster);
+ Mutex::Autolock autoLock(mExtractor->mLock);
+ advance_l();
+}
+
+void BlockIterator::advance_l() {
+ for (;;) {
+ long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
+ LOGV("GetEntry returned %ld", res);
+
+ long long pos;
+ long len;
+ if (res < 0) {
+ // Need to parse this cluster some more
+
+ CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
+
+ res = mCluster->Parse(pos, len);
+ LOGV("Parse returned %ld", res);
+
+ if (res < 0) {
+ // I/O error
+
+ LOGE("Cluster::Parse returned result %ld", res);
- if (eos()) {
+ mCluster = NULL;
break;
}
- mBlockEntry = mCluster->GetFirst();
+ continue;
+ } else if (res == 0) {
+ // We're done with this cluster
+
+ const mkvparser::Cluster *nextCluster;
+ res = mExtractor->mSegment->ParseNext(
+ mCluster, nextCluster, pos, len);
+ LOGV("ParseNext returned %ld", res);
+
+ if (res > 0) {
+ // EOF
+
+ mCluster = NULL;
+ break;
+ }
+
+ CHECK_EQ(res, 0);
+ CHECK(nextCluster != NULL);
+ CHECK(!nextCluster->EOS());
+
+ mCluster = nextCluster;
+
+ res = mCluster->Parse(pos, len);
+ LOGV("Parse (2) returned %ld", res);
+ CHECK_GE(res, 0);
+
+ mBlockEntryIndex = 0;
+ continue;
}
- if (mBlockEntry != NULL
- && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
+ CHECK(mBlockEntry != NULL);
+ CHECK(mBlockEntry->GetBlock() != NULL);
+ ++mBlockEntryIndex;
+
+ if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
break;
}
}
}
void BlockIterator::reset() {
- mCluster = mSegment->GetFirst();
- mBlockEntry = mCluster->GetFirst();
+ Mutex::Autolock autoLock(mExtractor->mLock);
- while (!eos() && block()->GetTrackNumber() != mTrackNum) {
- advance();
- }
+ mCluster = mExtractor->mSegment->GetFirst();
+ mBlockEntry = NULL;
+ mBlockEntryIndex = 0;
+
+ do {
+ advance_l();
+ } while (!eos() && block()->GetTrackNumber() != mTrackNum);
}
void BlockIterator::seek(int64_t seekTimeUs) {
- mCluster = mSegment->FindCluster(seekTimeUs * 1000ll);
- mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
+ Mutex::Autolock autoLock(mExtractor->mLock);
+
+ mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
+ mBlockEntry = NULL;
+ mBlockEntryIndex = 0;
- while (!eos() && block()->GetTrackNumber() != mTrackNum) {
- advance();
+ do {
+ advance_l();
}
+ while (!eos() && block()->GetTrackNumber() != mTrackNum);
while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
- advance();
+ advance_l();
}
}
@@ -291,16 +353,6 @@ void MatroskaSource::clearPendingFrames() {
}
}
-#define BAIL(err) \
- do { \
- if (bigbuf) { \
- bigbuf->release(); \
- bigbuf = NULL; \
- } \
- \
- return err; \
- } while (0)
-
status_t MatroskaSource::readBlock() {
CHECK(mPendingFrames.empty());
@@ -310,181 +362,39 @@ status_t MatroskaSource::readBlock() {
const mkvparser::Block *block = mBlockIter.block();
- size_t size = block->GetSize();
int64_t timeUs = mBlockIter.blockTimeUs();
- int32_t isSync = block->IsKey();
-
- MediaBuffer *bigbuf = new MediaBuffer(size);
-
- long res = block->Read(
- mExtractor->mReader, (unsigned char *)bigbuf->data());
-
- if (res != 0) {
- bigbuf->release();
- bigbuf = NULL;
-
- return ERROR_END_OF_STREAM;
- }
-
- mBlockIter.advance();
-
- bigbuf->meta_data()->setInt64(kKeyTime, timeUs);
- bigbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
-
- unsigned lacing = (block->Flags() >> 1) & 3;
-
- if (lacing == 0) {
- mPendingFrames.push_back(bigbuf);
- return OK;
- }
-
- LOGV("lacing = %u, size = %d", lacing, size);
-
- const uint8_t *data = (const uint8_t *)bigbuf->data();
- // hexdump(data, size);
-
- if (size == 0) {
- BAIL(ERROR_MALFORMED);
- }
-
- unsigned numFrames = (unsigned)data[0] + 1;
- ++data;
- --size;
-
- Vector<uint64_t> frameSizes;
-
- switch (lacing) {
- case 1: // Xiph
- {
- for (size_t i = 0; i < numFrames - 1; ++i) {
- size_t frameSize = 0;
- uint8_t byte;
- do {
- if (size == 0) {
- BAIL(ERROR_MALFORMED);
- }
- byte = data[0];
- ++data;
- --size;
-
- frameSize += byte;
- } while (byte == 0xff);
-
- frameSizes.push(frameSize);
- }
- break;
- }
-
- case 2: // fixed-size
- {
- if ((size % numFrames) != 0) {
- BAIL(ERROR_MALFORMED);
- }
-
- size_t frameSize = size / numFrames;
- for (size_t i = 0; i < numFrames - 1; ++i) {
- frameSizes.push(frameSize);
- }
-
- break;
- }
-
- case 3: // EBML
- {
- uint64_t lastFrameSize = 0;
- for (size_t i = 0; i < numFrames - 1; ++i) {
- uint8_t byte;
-
- if (size == 0) {
- BAIL(ERROR_MALFORMED);
- }
- byte = data[0];
- ++data;
- --size;
-
- size_t numLeadingZeroes = clz(byte);
-
- uint64_t frameSize = byte & ~(0x80 >> numLeadingZeroes);
- for (size_t j = 0; j < numLeadingZeroes; ++j) {
- if (size == 0) {
- BAIL(ERROR_MALFORMED);
- }
-
- frameSize = frameSize << 8;
- frameSize |= data[0];
- ++data;
- --size;
- }
-
- if (i == 0) {
- frameSizes.push(frameSize);
- } else {
- size_t shift =
- 7 - numLeadingZeroes + 8 * numLeadingZeroes;
-
- int64_t delta =
- (int64_t)frameSize - (1ll << (shift - 1)) + 1;
-
- frameSize = lastFrameSize + delta;
-
- frameSizes.push(frameSize);
- }
-
- lastFrameSize = frameSize;
- }
- break;
- }
+ for (int i = 0; i < block->GetFrameCount(); ++i) {
+ const mkvparser::Block::Frame &frame = block->GetFrame(i);
- default:
- TRESPASS();
- }
-
-#if 0
- AString out;
- for (size_t i = 0; i < frameSizes.size(); ++i) {
- if (i > 0) {
- out.append(", ");
- }
- out.append(StringPrintf("%llu", frameSizes.itemAt(i)));
- }
- LOGV("sizes = [%s]", out.c_str());
-#endif
+ MediaBuffer *mbuf = new MediaBuffer(frame.len);
+ mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+ mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
- for (size_t i = 0; i < frameSizes.size(); ++i) {
- uint64_t frameSize = frameSizes.itemAt(i);
+ long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
+ if (n != 0) {
+ mPendingFrames.clear();
- if (size < frameSize) {
- BAIL(ERROR_MALFORMED);
+ mBlockIter.advance();
+ return ERROR_IO;
}
- MediaBuffer *mbuf = new MediaBuffer(frameSize);
- mbuf->meta_data()->setInt64(kKeyTime, timeUs);
- mbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
- memcpy(mbuf->data(), data, frameSize);
mPendingFrames.push_back(mbuf);
-
- data += frameSize;
- size -= frameSize;
}
- size_t offset = bigbuf->range_length() - size;
- bigbuf->set_range(offset, size);
-
- mPendingFrames.push_back(bigbuf);
+ mBlockIter.advance();
return OK;
}
-#undef BAIL
-
status_t MatroskaSource::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
int64_t seekTimeUs;
ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ if (options && options->getSeekTo(&seekTimeUs, &mode)
+ && !mExtractor->isLiveStreaming()) {
clearPendingFrames();
mBlockIter.seek(seekTimeUs);
}
@@ -584,6 +494,13 @@ MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
mReader(new DataSourceReader(mDataSource)),
mSegment(NULL),
mExtractedThumbnails(false) {
+ off64_t size;
+ mIsLiveStreaming =
+ (mDataSource->flags()
+ & (DataSource::kWantsPrefetching
+ | DataSource::kIsCachingDataSource))
+ && mDataSource->getSize(&size) != OK;
+
mkvparser::EBMLHeader ebmlHeader;
long long pos;
if (ebmlHeader.Parse(mReader, pos) < 0) {
@@ -598,7 +515,16 @@ MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
return;
}
- ret = mSegment->Load();
+ if (isLiveStreaming()) {
+ ret = mSegment->ParseHeaders();
+ CHECK_EQ(ret, 0);
+
+ long len;
+ ret = mSegment->LoadCluster(pos, len);
+ CHECK_EQ(ret, 0);
+ } else {
+ ret = mSegment->Load();
+ }
if (ret < 0) {
delete mSegment;
@@ -635,7 +561,8 @@ sp<MetaData> MatroskaExtractor::getTrackMetaData(
return NULL;
}
- if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
+ if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
+ && !isLiveStreaming()) {
findThumbnails();
mExtractedThumbnails = true;
}
@@ -643,6 +570,10 @@ sp<MetaData> MatroskaExtractor::getTrackMetaData(
return mTracks.itemAt(index).mMeta;
}
+bool MatroskaExtractor::isLiveStreaming() const {
+ return mIsLiveStreaming;
+}
+
static void addESDSFromAudioSpecificInfo(
const sp<MetaData> &meta, const void *asi, size_t asiSize) {
static const uint8_t kStaticESDS[] = {
@@ -660,7 +591,8 @@ static void addESDSFromAudioSpecificInfo(
// AudioSpecificInfo (with size prefix) follows
};
- CHECK(asiSize < 128);
+ // Make sure all sizes can be coded in a single byte.
+ CHECK(asiSize + 22 - 2 < 128);
size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
uint8_t *esds = new uint8_t[esdsSize];
memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
@@ -668,6 +600,11 @@ static void addESDSFromAudioSpecificInfo(
*ptr++ = asiSize;
memcpy(ptr, asi, asiSize);
+ // Increment by codecPrivateSize less 2 bytes that are accounted for
+ // already in lengths of 22/17
+ esds[1] += asiSize - 2;
+ esds[6] += asiSize - 2;
+
meta->setData(kKeyESDS, 0, esds, esdsSize);
delete[] esds;
@@ -794,7 +731,7 @@ void MatroskaExtractor::findThumbnails() {
continue;
}
- BlockIterator iter(mSegment, info->mTrackNum);
+ BlockIterator iter(this, info->mTrackNum);
int32_t i = 0;
int64_t thumbnailTimeUs = 0;
size_t maxBlockSize = 0;
@@ -802,7 +739,11 @@ void MatroskaExtractor::findThumbnails() {
if (iter.block()->IsKey()) {
++i;
- size_t blockSize = iter.block()->GetSize();
+ size_t blockSize = 0;
+ for (int i = 0; i < iter.block()->GetFrameCount(); ++i) {
+ blockSize += iter.block()->GetFrame(i).len;
+ }
+
if (blockSize > maxBlockSize) {
maxBlockSize = blockSize;
thumbnailTimeUs = iter.blockTimeUs();
@@ -821,6 +762,15 @@ sp<MetaData> MatroskaExtractor::getMetaData() {
return meta;
}
+uint32_t MatroskaExtractor::flags() const {
+ uint32_t x = CAN_PAUSE;
+ if (!isLiveStreaming()) {
+ x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
+ }
+
+ return x;
+}
+
bool SniffMatroska(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index fa20b84..38ebd61 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -20,6 +20,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <utils/Vector.h>
+#include <utils/threads.h>
namespace mkvparser {
struct Segment;
@@ -45,26 +46,34 @@ struct MatroskaExtractor : public MediaExtractor {
virtual sp<MetaData> getMetaData();
+ virtual uint32_t flags() const;
+
protected:
virtual ~MatroskaExtractor();
private:
friend struct MatroskaSource;
+ friend struct BlockIterator;
struct TrackInfo {
unsigned long mTrackNum;
sp<MetaData> mMeta;
};
+
+ Mutex mLock;
Vector<TrackInfo> mTracks;
sp<DataSource> mDataSource;
DataSourceReader *mReader;
mkvparser::Segment *mSegment;
bool mExtractedThumbnails;
+ bool mIsLiveStreaming;
void addTracks();
void findThumbnails();
+ bool isLiveStreaming() const;
+
MatroskaExtractor(const MatroskaExtractor &);
MatroskaExtractor &operator=(const MatroskaExtractor &);
};
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 6cbd599..cdce772 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "OMXNodeInstance"
#include <utils/Log.h>
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 4f28855..54c0d77 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -487,14 +487,12 @@ static const char *GetURLForMime(const char *mime) {
{ "audio/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
{ "audio/amr-wb",
- "file:///sdcard/media_api/music_perf/AMRWB/"
- "NIN_AMR-WB_15.85kbps_16kbps.amr" },
+ "file:///sdcard/media_api/music/"
+ "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
{ "audio/mp4a-latm",
- "file:///sdcard/media_api/music_perf/AAC/"
- "WC_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4" },
+ "file:///sdcard/media_api/video/H264_AAC.3gp" },
{ "audio/mpeg",
- "file:///sdcard/media_api/music_perf/MP3/"
- "WC_256kbps_44.1khz_mono_CBR_DPA.mp3" }
+ "file:///sdcard/media_api/music/MP3CBR.mp3" }
};
for (size_t i = 0; i < sizeof(kMimeToURL) / sizeof(kMimeToURL[0]); ++i) {
@@ -626,8 +624,10 @@ status_t Harness::testSeek(
requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
}
- MediaBuffer *buffer;
- options.setSeekTo(requestedSeekTimeUs);
+ MediaBuffer *buffer = NULL;
+ options.setSeekTo(
+ requestedSeekTimeUs, MediaSource::ReadOptions::SEEK_NEXT_SYNC);
+
if (seekSource->read(&buffer, &options) != OK) {
CHECK_EQ(buffer, NULL);
actualSeekTimeUs = -1;
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 0740515..c4e0cdc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -20,6 +20,8 @@
#include "ARTSPConnection.h"
+#include <cutils/properties.h>
+
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -44,6 +46,7 @@ ARTSPConnection::ARTSPConnection()
mConnectionID(0),
mNextCSeq(0),
mReceiveResponseEventPending(false) {
+ MakeUserAgent(&mUserAgent);
}
ARTSPConnection::~ARTSPConnection() {
@@ -378,6 +381,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
reply->setString("original-request", request.c_str(), request.size());
addAuthentication(&request);
+ addUserAgent(&request);
// Find the boundary between headers and the body.
ssize_t i = request.find("\r\n\r\n");
@@ -979,4 +983,27 @@ void ARTSPConnection::addAuthentication(AString *request) {
#endif
}
+// static
+void ARTSPConnection::MakeUserAgent(AString *userAgent) {
+ userAgent->clear();
+ userAgent->setTo("User-Agent: stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.version.release", value, "Unknown");
+ userAgent->append(value);
+ userAgent->append(")\r\n");
+}
+
+void ARTSPConnection::addUserAgent(AString *request) const {
+ // Find the boundary between headers and the body.
+ ssize_t i = request->find("\r\n\r\n");
+ CHECK_GE(i, 0);
+
+ request->insert(mUserAgent, i + 2);
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 0fecf3c6..ac2e3ae 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -87,6 +87,8 @@ private:
sp<AMessage> mObserveBinaryMessage;
+ AString mUserAgent;
+
void onConnect(const sp<AMessage> &msg);
void onDisconnect(const sp<AMessage> &msg);
void onCompleteConnection(const sp<AMessage> &msg);
@@ -106,6 +108,8 @@ private:
bool parseAuthMethod(const sp<ARTSPResponse> &response);
void addAuthentication(AString *request);
+ void addUserAgent(AString *request) const;
+
status_t findPendingRequest(
const sp<ARTSPResponse> &response, ssize_t *index) const;
@@ -114,6 +118,8 @@ private:
static bool ParseSingleUnsignedLong(
const char *from, unsigned long *x);
+ static void MakeUserAgent(AString *userAgent);
+
DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
};
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index 7697e3c..a4253f6 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -10,6 +10,6 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE:= libstagefright_yuv
-LOCAL_PRELINK_MODULE := false
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
deleted file mode 100644
index d926cb1..0000000
--- a/services/audioflinger/A2dpAudioInterface.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (C) 2008 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 <math.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "A2dpAudioInterface"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "A2dpAudioInterface.h"
-#include "audio/liba2dp.h"
-#include <hardware_legacy/power.h>
-
-namespace android {
-
-static const char *sA2dpWakeLock = "A2dpOutputStream";
-#define MAX_WRITE_RETRIES 5
-
-// ----------------------------------------------------------------------------
-
-//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
-//{
-// AudioHardwareInterface* hw = 0;
-//
-// hw = AudioHardwareInterface::create();
-// LOGD("new A2dpAudioInterface(hw: %p)", hw);
-// hw = new A2dpAudioInterface(hw);
-// return hw;
-//}
-
-A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
- mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
-{
-}
-
-A2dpAudioInterface::~A2dpAudioInterface()
-{
- closeOutputStream((AudioStreamOut *)mOutput);
- delete mHardwareInterface;
-}
-
-status_t A2dpAudioInterface::initCheck()
-{
- if (mHardwareInterface == 0) return NO_INIT;
- return mHardwareInterface->initCheck();
-}
-
-AudioStreamOut* A2dpAudioInterface::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
- LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
- return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
- }
-
- status_t err = 0;
-
- // only one output stream allowed
- if (mOutput) {
- if (status)
- *status = -1;
- return NULL;
- }
-
- // create new output stream
- A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
- if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
- mOutput = out;
- mOutput->setBluetoothEnabled(mBluetoothEnabled);
- mOutput->setSuspended(mSuspended);
- } else {
- delete out;
- }
-
- if (status)
- *status = err;
- return mOutput;
-}
-
-void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
- if (mOutput == 0 || mOutput != out) {
- mHardwareInterface->closeOutputStream(out);
- }
- else {
- delete mOutput;
- mOutput = 0;
- }
-}
-
-
-AudioStreamIn* A2dpAudioInterface::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
- AudioSystem::audio_in_acoustics acoustics)
-{
- return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
-}
-
-void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
-{
- return mHardwareInterface->closeInputStream(in);
-}
-
-status_t A2dpAudioInterface::setMode(int mode)
-{
- return mHardwareInterface->setMode(mode);
-}
-
-status_t A2dpAudioInterface::setMicMute(bool state)
-{
- return mHardwareInterface->setMicMute(state);
-}
-
-status_t A2dpAudioInterface::getMicMute(bool* state)
-{
- return mHardwareInterface->getMicMute(state);
-}
-
-status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- String8 key;
- status_t status = NO_ERROR;
-
- LOGV("setParameters() %s", keyValuePairs.string());
-
- key = "bluetooth_enabled";
- if (param.get(key, value) == NO_ERROR) {
- mBluetoothEnabled = (value == "true");
- if (mOutput) {
- mOutput->setBluetoothEnabled(mBluetoothEnabled);
- }
- param.remove(key);
- }
- key = String8("A2dpSuspended");
- if (param.get(key, value) == NO_ERROR) {
- mSuspended = (value == "true");
- if (mOutput) {
- mOutput->setSuspended(mSuspended);
- }
- param.remove(key);
- }
-
- if (param.size()) {
- status_t hwStatus = mHardwareInterface->setParameters(param.toString());
- if (status == NO_ERROR) {
- status = hwStatus;
- }
- }
-
- return status;
-}
-
-String8 A2dpAudioInterface::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- AudioParameter a2dpParam = AudioParameter();
- String8 value;
- String8 key;
-
- key = "bluetooth_enabled";
- if (param.get(key, value) == NO_ERROR) {
- value = mBluetoothEnabled ? "true" : "false";
- a2dpParam.add(key, value);
- param.remove(key);
- }
- key = "A2dpSuspended";
- if (param.get(key, value) == NO_ERROR) {
- value = mSuspended ? "true" : "false";
- a2dpParam.add(key, value);
- param.remove(key);
- }
-
- String8 keyValuePairs = a2dpParam.toString();
-
- if (param.size()) {
- if (keyValuePairs != "") {
- keyValuePairs += ";";
- }
- keyValuePairs += mHardwareInterface->getParameters(param.toString());
- }
-
- LOGV("getParameters() %s", keyValuePairs.string());
- return keyValuePairs;
-}
-
-size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-status_t A2dpAudioInterface::setVoiceVolume(float v)
-{
- return mHardwareInterface->setVoiceVolume(v);
-}
-
-status_t A2dpAudioInterface::setMasterVolume(float v)
-{
- return mHardwareInterface->setMasterVolume(v);
-}
-
-status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
-{
- return mHardwareInterface->dumpState(fd, args);
-}
-
-// ----------------------------------------------------------------------------
-
-A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
- mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
- // assume BT enabled to start, this is safe because its only the
- // enabled->disabled transition we are worried about
- mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
-{
- // use any address by default
- strcpy(mA2dpAddress, "00:00:00:00:00:00");
- init();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
- uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
-{
- int lFormat = pFormat ? *pFormat : 0;
- uint32_t lChannels = pChannels ? *pChannels : 0;
- uint32_t lRate = pRate ? *pRate : 0;
-
- LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
-
- // fix up defaults
- if (lFormat == 0) lFormat = format();
- if (lChannels == 0) lChannels = channels();
- if (lRate == 0) lRate = sampleRate();
-
- // check values
- if ((lFormat != format()) ||
- (lChannels != channels()) ||
- (lRate != sampleRate())){
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- if (pFormat) *pFormat = lFormat;
- if (pChannels) *pChannels = lChannels;
- if (pRate) *pRate = lRate;
-
- mDevice = device;
- mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
- return NO_ERROR;
-}
-
-A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
-{
- LOGV("A2dpAudioStreamOut destructor");
- close();
- LOGV("A2dpAudioStreamOut destructor returning from close()");
-}
-
-ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
-{
- status_t status = -1;
- {
- Mutex::Autolock lock(mLock);
-
- size_t remaining = bytes;
-
- if (!mBluetoothEnabled || mClosing || mSuspended) {
- LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
- mBluetoothEnabled %d, mClosing %d, mSuspended %d",
- mBluetoothEnabled, mClosing, mSuspended);
- goto Error;
- }
-
- if (mStandby) {
- acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
- mStandby = false;
- mLastWriteTime = systemTime();
- }
-
- status = init();
- if (status < 0)
- goto Error;
-
- int retries = MAX_WRITE_RETRIES;
- while (remaining > 0 && retries) {
- status = a2dp_write(mData, buffer, remaining);
- if (status < 0) {
- LOGE("a2dp_write failed err: %d\n", status);
- goto Error;
- }
- if (status == 0) {
- retries--;
- }
- remaining -= status;
- buffer = (char *)buffer + status;
- }
-
- // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
- // does no spin and starve other threads.
- // NOTE: It is likely that the A2DP headset is being disconnected
- nsecs_t now = systemTime();
- if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
- LOGV("A2DP sink runs too fast");
- usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
- }
- mLastWriteTime = now;
- return bytes;
-
- }
-Error:
-
- standby();
-
- // Simulate audio output timing in case of error
- usleep(mBufferDurationUs);
-
- return status;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
-{
- if (!mData) {
- status_t status = a2dp_init(44100, 2, &mData);
- if (status < 0) {
- LOGE("a2dp_init failed err: %d\n", status);
- mData = NULL;
- return status;
- }
- a2dp_set_sink(mData, mA2dpAddress);
- }
-
- return 0;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
-{
- Mutex::Autolock lock(mLock);
- return standby_l();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l()
-{
- int result = NO_ERROR;
-
- if (!mStandby) {
- LOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d",
- mClosing, mBluetoothEnabled);
- if (!mClosing && mBluetoothEnabled) {
- result = a2dp_stop(mData);
- }
- release_wake_lock(sA2dpWakeLock);
- mStandby = true;
- }
-
- return result;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- String8 key = String8("a2dp_sink_address");
- status_t status = NO_ERROR;
- int device;
- LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
-
- if (param.get(key, value) == NO_ERROR) {
- if (value.length() != strlen("00:00:00:00:00:00")) {
- status = BAD_VALUE;
- } else {
- setAddress(value.string());
- }
- param.remove(key);
- }
- key = String8("closing");
- if (param.get(key, value) == NO_ERROR) {
- mClosing = (value == "true");
- if (mClosing) {
- standby();
- }
- param.remove(key);
- }
- key = AudioParameter::keyRouting;
- if (param.getInt(key, device) == NO_ERROR) {
- if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
- mDevice = device;
- status = NO_ERROR;
- } else {
- status = BAD_VALUE;
- }
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8("a2dp_sink_address");
-
- if (param.get(key, value) == NO_ERROR) {
- value = mA2dpAddress;
- param.add(key, value);
- }
- key = AudioParameter::keyRouting;
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
-{
- Mutex::Autolock lock(mLock);
-
- if (strlen(address) != strlen("00:00:00:00:00:00"))
- return -EINVAL;
-
- strcpy(mA2dpAddress, address);
- if (mData)
- a2dp_set_sink(mData, mA2dpAddress);
-
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
-{
- LOGD("setBluetoothEnabled %d", enabled);
-
- Mutex::Autolock lock(mLock);
-
- mBluetoothEnabled = enabled;
- if (!enabled) {
- return close_l();
- }
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
-{
- LOGV("setSuspended %d", onOff);
- mSuspended = onOff;
- standby();
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
-{
- Mutex::Autolock lock(mLock);
- LOGV("A2dpAudioStreamOut::close() calling close_l()");
- return close_l();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
-{
- standby_l();
- if (mData) {
- LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
- a2dp_cleanup(mData);
- mData = NULL;
- }
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
-{
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
-{
- //TODO: enable when supported by driver
- return INVALID_OPERATION;
-}
-
-}; // namespace android
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
deleted file mode 100644
index dbe2c6a..0000000
--- a/services/audioflinger/A2dpAudioInterface.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 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 A2DP_AUDIO_HARDWARE_H
-#define A2DP_AUDIO_HARDWARE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-
-namespace android {
-
-class A2dpAudioInterface : public AudioHardwareBase
-{
- class A2dpAudioStreamOut;
-
-public:
- A2dpAudioInterface(AudioHardwareInterface* hw);
- virtual ~A2dpAudioInterface();
- virtual status_t initCheck();
-
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- virtual status_t setMode(int mode);
-
- // mic mute
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool* state);
-
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-// static AudioHardwareInterface* createA2dpInterface();
-
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
-private:
- class A2dpAudioStreamOut : public AudioStreamOut {
- public:
- A2dpAudioStreamOut();
- virtual ~A2dpAudioStreamOut();
- status_t set(uint32_t device,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate);
- virtual uint32_t sampleRate() const { return 44100; }
- // SBC codec wants a multiple of 512
- virtual size_t bufferSize() const { return 512 * 20; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; }
- virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
- private:
- friend class A2dpAudioInterface;
- status_t init();
- status_t close();
- status_t close_l();
- status_t setAddress(const char* address);
- status_t setBluetoothEnabled(bool enabled);
- status_t setSuspended(bool onOff);
- status_t standby_l();
-
- private:
- int mFd;
- bool mStandby;
- int mStartCount;
- int mRetryCount;
- char mA2dpAddress[20];
- void* mData;
- Mutex mLock;
- bool mBluetoothEnabled;
- uint32_t mDevice;
- bool mClosing;
- bool mSuspended;
- nsecs_t mLastWriteTime;
- uint32_t mBufferDurationUs;
- };
-
- friend class A2dpAudioStreamOut;
-
- A2dpAudioStreamOut* mOutput;
- AudioHardwareInterface *mHardwareInterface;
- char mA2dpAddress[20];
- bool mBluetoothEnabled;
- bool mSuspended;
-};
-
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // A2DP_AUDIO_HARDWARE_H
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 69a4adc..2222e8b 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -1,77 +1,5 @@
LOCAL_PATH:= $(call my-dir)
-#AUDIO_POLICY_TEST := true
-#ENABLE_AUDIO_DUMP := true
-
-include $(CLEAR_VARS)
-
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- ENABLE_AUDIO_DUMP := true
-endif
-
-
-LOCAL_SRC_FILES:= \
- AudioHardwareGeneric.cpp \
- AudioHardwareStub.cpp \
- AudioHardwareInterface.cpp
-
-ifeq ($(ENABLE_AUDIO_DUMP),true)
- LOCAL_SRC_FILES += AudioDumpInterface.cpp
- LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
-endif
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libmedia \
- libhardware_legacy
-
-ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
- LOCAL_CFLAGS += -DGENERIC_AUDIO
-endif
-
-LOCAL_MODULE:= libaudiointerface
-
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_SRC_FILES += A2dpAudioInterface.cpp
- LOCAL_SHARED_LIBRARIES += liba2dp
- LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
- LOCAL_C_INCLUDES += $(call include-path-for, bluez)
-endif
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioPolicyManagerBase.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libmedia
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-LOCAL_MODULE:= libaudiopolicybase
-
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_CFLAGS += -DWITH_A2DP
-endif
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
-endif
-
-include $(BUILD_STATIC_LIBRARY)
-
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
@@ -87,15 +15,12 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder \
libmedia \
+ libhardware \
libhardware_legacy \
libeffects
-ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
- LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
- LOCAL_CFLAGS += -DGENERIC_AUDIO
-else
- LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
-endif
+LOCAL_STATIC_LIBRARIES := \
+ libmedia_helper
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
@@ -105,15 +30,6 @@ endif
LOCAL_MODULE:= libaudioflinger
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
- LOCAL_SHARED_LIBRARIES += liba2dp
-endif
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
-endif
-
ifeq ($(TARGET_SIMULATOR),true)
ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lrt -lpthread
diff --git a/services/audioflinger/AudioDumpInterface.cpp b/services/audioflinger/AudioDumpInterface.cpp
deleted file mode 100644
index 6c11114..0000000
--- a/services/audioflinger/AudioDumpInterface.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-/* //device/servers/AudioFlinger/AudioDumpInterface.cpp
-**
-** Copyright 2008, 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_TAG "AudioFlingerDump"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "AudioDumpInterface.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
- : mPolicyCommands(String8("")), mFileName(String8(""))
-{
- if(hw == 0) {
- LOGE("Dump construct hw = 0");
- }
- mFinalInterface = hw;
- LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
-}
-
-
-AudioDumpInterface::~AudioDumpInterface()
-{
- for (size_t i = 0; i < mOutputs.size(); i++) {
- closeOutputStream((AudioStreamOut *)mOutputs[i]);
- }
-
- for (size_t i = 0; i < mInputs.size(); i++) {
- closeInputStream((AudioStreamIn *)mInputs[i]);
- }
-
- if(mFinalInterface) delete mFinalInterface;
-}
-
-
-AudioStreamOut* AudioDumpInterface::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AudioStreamOut* outFinal = NULL;
- int lFormat = AudioSystem::PCM_16_BIT;
- uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
- uint32_t lRate = 44100;
-
-
- outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
- if (outFinal != 0) {
- lFormat = outFinal->format();
- lChannels = outFinal->channels();
- lRate = outFinal->sampleRate();
- } else {
- if (format != 0) {
- if (*format != 0) {
- lFormat = *format;
- } else {
- *format = lFormat;
- }
- }
- if (channels != 0) {
- if (*channels != 0) {
- lChannels = *channels;
- } else {
- *channels = lChannels;
- }
- }
- if (sampleRate != 0) {
- if (*sampleRate != 0) {
- lRate = *sampleRate;
- } else {
- *sampleRate = lRate;
- }
- }
- if (status) *status = NO_ERROR;
- }
- LOGV("openOutputStream(), outFinal %p", outFinal);
-
- AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
- devices, lFormat, lChannels, lRate);
- mOutputs.add(dumOutput);
-
- return dumOutput;
-}
-
-void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
-{
- AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
-
- if (mOutputs.indexOf(dumpOut) < 0) {
- LOGW("Attempt to close invalid output stream");
- return;
- }
-
- LOGV("closeOutputStream() output %p", out);
-
- dumpOut->standby();
- if (dumpOut->finalStream() != NULL) {
- mFinalInterface->closeOutputStream(dumpOut->finalStream());
- }
-
- mOutputs.remove(dumpOut);
- delete dumpOut;
-}
-
-AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
- uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- AudioStreamIn* inFinal = NULL;
- int lFormat = AudioSystem::PCM_16_BIT;
- uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
- uint32_t lRate = 8000;
-
- inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
- if (inFinal != 0) {
- lFormat = inFinal->format();
- lChannels = inFinal->channels();
- lRate = inFinal->sampleRate();
- } else {
- if (format != 0) {
- if (*format != 0) {
- lFormat = *format;
- } else {
- *format = lFormat;
- }
- }
- if (channels != 0) {
- if (*channels != 0) {
- lChannels = *channels;
- } else {
- *channels = lChannels;
- }
- }
- if (sampleRate != 0) {
- if (*sampleRate != 0) {
- lRate = *sampleRate;
- } else {
- *sampleRate = lRate;
- }
- }
- if (status) *status = NO_ERROR;
- }
- LOGV("openInputStream(), inFinal %p", inFinal);
-
- AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
- devices, lFormat, lChannels, lRate);
- mInputs.add(dumInput);
-
- return dumInput;
-}
-void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
-{
- AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
-
- if (mInputs.indexOf(dumpIn) < 0) {
- LOGW("Attempt to close invalid input stream");
- return;
- }
- dumpIn->standby();
- if (dumpIn->finalStream() != NULL) {
- mFinalInterface->closeInputStream(dumpIn->finalStream());
- }
-
- mInputs.remove(dumpIn);
- delete dumpIn;
-}
-
-
-status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- int valueInt;
- LOGV("setParameters %s", keyValuePairs.string());
-
- if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
- mFileName = value;
- param.remove(String8("test_cmd_file_name"));
- }
- if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
- Mutex::Autolock _l(mLock);
- param.remove(String8("test_cmd_policy"));
- mPolicyCommands = param.toString();
- LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
- return NO_ERROR;
- }
-
- if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
- return NO_ERROR;
-}
-
-String8 AudioDumpInterface::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- AudioParameter response;
- String8 value;
-
-// LOGV("getParameters %s", keys.string());
- if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
- Mutex::Autolock _l(mLock);
- if (mPolicyCommands.length() != 0) {
- response = AudioParameter(mPolicyCommands);
- response.addInt(String8("test_cmd_policy"), 1);
- } else {
- response.addInt(String8("test_cmd_policy"), 0);
- }
- param.remove(String8("test_cmd_policy"));
-// LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
- }
-
- if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
- response.add(String8("test_cmd_file_name"), mFileName);
- param.remove(String8("test_cmd_file_name"));
- }
-
- String8 keyValuePairs = response.toString();
-
- if (param.size() && mFinalInterface != 0 ) {
- keyValuePairs += ";";
- keyValuePairs += mFinalInterface->getParameters(param.toString());
- }
-
- return keyValuePairs;
-}
-
-status_t AudioDumpInterface::setMode(int mode)
-{
- return mFinalInterface->setMode(mode);
-}
-
-size_t AudioDumpInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- return mFinalInterface->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-// ----------------------------------------------------------------------------
-
-AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
- int id,
- AudioStreamOut* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate)
- : mInterface(interface), mId(id),
- mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
- mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
-{
- LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
-}
-
-
-AudioStreamOutDump::~AudioStreamOutDump()
-{
- LOGV("AudioStreamOutDump destructor");
- Close();
-}
-
-ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
-{
- ssize_t ret;
-
- if (mFinalStream) {
- ret = mFinalStream->write(buffer, bytes);
- } else {
- usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
- ret = bytes;
- }
- if(!mFile) {
- if (mInterface->fileName() != "") {
- char name[255];
- sprintf(name, "%s_out_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
- mFile = fopen(name, "wb");
- LOGV("Opening dump file %s, fh %p", name, mFile);
- }
- }
- if (mFile) {
- fwrite(buffer, bytes, 1, mFile);
- }
- return ret;
-}
-
-status_t AudioStreamOutDump::standby()
-{
- LOGV("AudioStreamOutDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
-
- Close();
- if (mFinalStream != 0 ) return mFinalStream->standby();
- return NO_ERROR;
-}
-
-uint32_t AudioStreamOutDump::sampleRate() const
-{
- if (mFinalStream != 0 ) return mFinalStream->sampleRate();
- return mSampleRate;
-}
-
-size_t AudioStreamOutDump::bufferSize() const
-{
- if (mFinalStream != 0 ) return mFinalStream->bufferSize();
- return mBufferSize;
-}
-
-uint32_t AudioStreamOutDump::channels() const
-{
- if (mFinalStream != 0 ) return mFinalStream->channels();
- return mChannels;
-}
-int AudioStreamOutDump::format() const
-{
- if (mFinalStream != 0 ) return mFinalStream->format();
- return mFormat;
-}
-uint32_t AudioStreamOutDump::latency() const
-{
- if (mFinalStream != 0 ) return mFinalStream->latency();
- return 0;
-}
-status_t AudioStreamOutDump::setVolume(float left, float right)
-{
- if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
- return NO_ERROR;
-}
-status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
-{
- LOGV("AudioStreamOutDump::setParameters %s", keyValuePairs.string());
-
- if (mFinalStream != 0 ) {
- return mFinalStream->setParameters(keyValuePairs);
- }
-
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- int valueInt;
- status_t status = NO_ERROR;
-
- if (param.getInt(String8("set_id"), valueInt) == NO_ERROR) {
- mId = valueInt;
- }
-
- if (param.getInt(String8("format"), valueInt) == NO_ERROR) {
- if (mFile == 0) {
- mFormat = valueInt;
- } else {
- status = INVALID_OPERATION;
- }
- }
- if (param.getInt(String8("channels"), valueInt) == NO_ERROR) {
- if (valueInt == AudioSystem::CHANNEL_OUT_STEREO || valueInt == AudioSystem::CHANNEL_OUT_MONO) {
- mChannels = valueInt;
- } else {
- status = BAD_VALUE;
- }
- }
- if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) {
- if (valueInt > 0 && valueInt <= 48000) {
- if (mFile == 0) {
- mSampleRate = valueInt;
- } else {
- status = INVALID_OPERATION;
- }
- } else {
- status = BAD_VALUE;
- }
- }
- return status;
-}
-
-String8 AudioStreamOutDump::getParameters(const String8& keys)
-{
- if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
-
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
-{
- if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
- return NO_ERROR;
-}
-
-void AudioStreamOutDump::Close()
-{
- if(mFile) {
- fclose(mFile);
- mFile = 0;
- }
-}
-
-status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames)
-{
- if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames);
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
- int id,
- AudioStreamIn* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate)
- : mInterface(interface), mId(id),
- mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
- mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
-{
- LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
-}
-
-
-AudioStreamInDump::~AudioStreamInDump()
-{
- Close();
-}
-
-ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
-{
- ssize_t ret;
-
- if (mFinalStream) {
- ret = mFinalStream->read(buffer, bytes);
- if(!mFile) {
- if (mInterface->fileName() != "") {
- char name[255];
- sprintf(name, "%s_in_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
- mFile = fopen(name, "wb");
- LOGV("Opening input dump file %s, fh %p", name, mFile);
- }
- }
- if (mFile) {
- fwrite(buffer, bytes, 1, mFile);
- }
- } else {
- usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
- ret = bytes;
- if(!mFile) {
- char name[255];
- strcpy(name, "/sdcard/music/sine440");
- if (channels() == AudioSystem::CHANNEL_IN_MONO) {
- strcat(name, "_mo");
- } else {
- strcat(name, "_st");
- }
- if (format() == AudioSystem::PCM_16_BIT) {
- strcat(name, "_16b");
- } else {
- strcat(name, "_8b");
- }
- if (sampleRate() < 16000) {
- strcat(name, "_8k");
- } else if (sampleRate() < 32000) {
- strcat(name, "_22k");
- } else if (sampleRate() < 48000) {
- strcat(name, "_44k");
- } else {
- strcat(name, "_48k");
- }
- strcat(name, ".wav");
- mFile = fopen(name, "rb");
- LOGV("Opening input read file %s, fh %p", name, mFile);
- if (mFile) {
- fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
- }
- }
- if (mFile) {
- ssize_t bytesRead = fread(buffer, bytes, 1, mFile);
- if (bytesRead >=0 && bytesRead < bytes) {
- fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
- fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mFile);
- }
- }
- }
-
- return ret;
-}
-
-status_t AudioStreamInDump::standby()
-{
- LOGV("AudioStreamInDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
-
- Close();
- if (mFinalStream != 0 ) return mFinalStream->standby();
- return NO_ERROR;
-}
-
-status_t AudioStreamInDump::setGain(float gain)
-{
- if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
- return NO_ERROR;
-}
-
-uint32_t AudioStreamInDump::sampleRate() const
-{
- if (mFinalStream != 0 ) return mFinalStream->sampleRate();
- return mSampleRate;
-}
-
-size_t AudioStreamInDump::bufferSize() const
-{
- if (mFinalStream != 0 ) return mFinalStream->bufferSize();
- return mBufferSize;
-}
-
-uint32_t AudioStreamInDump::channels() const
-{
- if (mFinalStream != 0 ) return mFinalStream->channels();
- return mChannels;
-}
-
-int AudioStreamInDump::format() const
-{
- if (mFinalStream != 0 ) return mFinalStream->format();
- return mFormat;
-}
-
-status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
-{
- LOGV("AudioStreamInDump::setParameters()");
- if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
- return NO_ERROR;
-}
-
-String8 AudioStreamInDump::getParameters(const String8& keys)
-{
- if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
-
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-unsigned int AudioStreamInDump::getInputFramesLost() const
-{
- if (mFinalStream != 0 ) return mFinalStream->getInputFramesLost();
- return 0;
-}
-
-status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
-{
- if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
- return NO_ERROR;
-}
-
-void AudioStreamInDump::Close()
-{
- if(mFile) {
- fclose(mFile);
- mFile = 0;
- }
-}
-}; // namespace android
diff --git a/services/audioflinger/AudioDumpInterface.h b/services/audioflinger/AudioDumpInterface.h
deleted file mode 100644
index 814ce5f..0000000
--- a/services/audioflinger/AudioDumpInterface.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* //device/servers/AudioFlinger/AudioDumpInterface.h
-**
-** Copyright 2008, 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 ANDROID_AUDIO_DUMP_INTERFACE_H
-#define ANDROID_AUDIO_DUMP_INTERFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/String8.h>
-#include <utils/SortedVector.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-#define AUDIO_DUMP_WAVE_HDR_SIZE 44
-
-class AudioDumpInterface;
-
-class AudioStreamOutDump : public AudioStreamOut {
-public:
- AudioStreamOutDump(AudioDumpInterface *interface,
- int id,
- AudioStreamOut* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate);
- ~AudioStreamOutDump();
-
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual uint32_t sampleRate() const;
- virtual size_t bufferSize() const;
- virtual uint32_t channels() const;
- virtual int format() const;
- virtual uint32_t latency() const;
- virtual status_t setVolume(float left, float right);
- virtual status_t standby();
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t dump(int fd, const Vector<String16>& args);
- void Close(void);
- AudioStreamOut* finalStream() { return mFinalStream; }
- uint32_t device() { return mDevice; }
- int getId() { return mId; }
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
-private:
- AudioDumpInterface *mInterface;
- int mId;
- uint32_t mSampleRate; //
- uint32_t mFormat; //
- uint32_t mChannels; // output configuration
- uint32_t mLatency; //
- uint32_t mDevice; // current device this output is routed to
- size_t mBufferSize;
- AudioStreamOut *mFinalStream;
- FILE *mFile; // output file
- int mFileCount;
-};
-
-class AudioStreamInDump : public AudioStreamIn {
-public:
- AudioStreamInDump(AudioDumpInterface *interface,
- int id,
- AudioStreamIn* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate);
- ~AudioStreamInDump();
-
- virtual uint32_t sampleRate() const;
- virtual size_t bufferSize() const;
- virtual uint32_t channels() const;
- virtual int format() const;
-
- virtual status_t setGain(float gain);
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t standby();
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const;
- virtual status_t dump(int fd, const Vector<String16>& args);
- void Close(void);
- AudioStreamIn* finalStream() { return mFinalStream; }
- uint32_t device() { return mDevice; }
-
-private:
- AudioDumpInterface *mInterface;
- int mId;
- uint32_t mSampleRate; //
- uint32_t mFormat; //
- uint32_t mChannels; // output configuration
- uint32_t mDevice; // current device this output is routed to
- size_t mBufferSize;
- AudioStreamIn *mFinalStream;
- FILE *mFile; // output file
- int mFileCount;
-};
-
-class AudioDumpInterface : public AudioHardwareBase
-{
-
-public:
- AudioDumpInterface(AudioHardwareInterface* hw);
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual ~AudioDumpInterface();
-
- virtual status_t initCheck()
- {return mFinalInterface->initCheck();}
- virtual status_t setVoiceVolume(float volume)
- {return mFinalInterface->setVoiceVolume(volume);}
- virtual status_t setMasterVolume(float volume)
- {return mFinalInterface->setMasterVolume(volume);}
-
- virtual status_t setMode(int mode);
-
- // mic mute
- virtual status_t setMicMute(bool state)
- {return mFinalInterface->setMicMute(state);}
- virtual status_t getMicMute(bool* state)
- {return mFinalInterface->getMicMute(state);}
-
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-
- virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels,
- uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
- virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
-
- String8 fileName() const { return mFileName; }
-protected:
-
- AudioHardwareInterface *mFinalInterface;
- SortedVector<AudioStreamOutDump *> mOutputs;
- SortedVector<AudioStreamInDump *> mInputs;
- Mutex mLock;
- String8 mPolicyCommands;
- String8 mFileName;
-};
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_DUMP_INTERFACE_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 2b08ab5..f8ad5bb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -31,7 +31,9 @@
#include <binder/IPCThreadState.h>
#include <utils/String16.h>
#include <utils/threads.h>
+#include <utils/Atomic.h>
+#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <media/AudioTrack.h>
@@ -40,15 +42,13 @@
#include <private/media/AudioTrackShared.h>
#include <private/media/AudioEffectShared.h>
-#include <hardware_legacy/AudioHardwareInterface.h>
+
+#include <hardware/audio.h>
+#include <hardware/audio_hal.h>
#include "AudioMixer.h"
#include "AudioFlinger.h"
-#ifdef WITH_A2DP
-#include "A2dpAudioInterface.h"
-#endif
-
#include <media/EffectsFactoryApi.h>
#include <media/EffectVisualizerApi.h>
@@ -136,34 +136,109 @@ static void addBatteryData(uint32_t params) {
service->addBatteryData(params);
}
+static int load_audio_interface(const char *if_name, const hw_module_t **mod,
+ audio_hw_device_t **dev)
+{
+ int rc;
+
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
+ if (rc)
+ goto out;
+
+ rc = audio_hw_device_open(*mod, dev);
+ LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
+ AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+ if (rc)
+ goto out;
+
+ return 0;
+
+out:
+ *mod = NULL;
+ *dev = NULL;
+ return rc;
+}
+
+static const char *audio_interfaces[] = {
+ "primary",
+ "a2dp",
+ "usb",
+};
+#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
+
// ----------------------------------------------------------------------------
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
- mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
+ mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
+{
+}
+
+void AudioFlinger::onFirstRef()
{
+ int rc = 0;
+
Mutex::Autolock _l(mLock);
+ /* TODO: move all this work into an Init() function */
mHardwareStatus = AUDIO_HW_IDLE;
- mAudioHardware = AudioHardwareInterface::create();
+ for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
+ const hw_module_t *mod;
+ audio_hw_device_t *dev;
+
+ rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
+ if (rc)
+ continue;
+
+ LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
+ mod->name, mod->id);
+ mAudioHwDevs.push(dev);
+
+ if (!mPrimaryHardwareDev) {
+ mPrimaryHardwareDev = dev;
+ LOGI("Using '%s' (%s.%s) as the primary audio interface",
+ mod->name, mod->id, audio_interfaces[i]);
+ }
+ }
mHardwareStatus = AUDIO_HW_INIT;
- if (mAudioHardware->initCheck() == NO_ERROR) {
- AutoMutex lock(mHardwareLock);
- mMode = AudioSystem::MODE_NORMAL;
- mHardwareStatus = AUDIO_HW_SET_MODE;
- mAudioHardware->setMode(mMode);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- mAudioHardware->setMasterVolume(1.0f);
- mHardwareStatus = AUDIO_HW_IDLE;
- } else {
- LOGE("Couldn't even initialize the stubbed audio hardware!");
+
+ if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
+ LOGE("Primary audio interface not found");
+ return;
}
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+
+ mHardwareStatus = AUDIO_HW_INIT;
+ rc = dev->init_check(dev);
+ if (rc == 0) {
+ AutoMutex lock(mHardwareLock);
+
+ mMode = AUDIO_MODE_NORMAL;
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ dev->set_mode(dev, mMode);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ dev->set_master_volume(dev, 1.0f);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+ }
+}
+
+status_t AudioFlinger::initCheck() const
+{
+ Mutex::Autolock _l(mLock);
+ if (mPrimaryHardwareDev == NULL || mAudioHwDevs.size() == 0)
+ return NO_INIT;
+ return NO_ERROR;
}
AudioFlinger::~AudioFlinger()
{
+ int num_devs = mAudioHwDevs.size();
+
while (!mRecordThreads.isEmpty()) {
// closeInput() will remove first entry from mRecordThreads
closeInput(mRecordThreads.keyAt(0));
@@ -172,12 +247,24 @@ AudioFlinger::~AudioFlinger()
// closeOutput() will remove first entry from mPlaybackThreads
closeOutput(mPlaybackThreads.keyAt(0));
}
- if (mAudioHardware) {
- delete mAudioHardware;
+
+ for (int i = 0; i < num_devs; i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ audio_hw_device_close(dev);
}
+ mAudioHwDevs.clear();
}
-
+audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
+{
+ /* first matching HW device is returned */
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ if ((dev->get_supported_devices(dev) & devices) == devices)
+ return dev;
+ }
+ return NULL;
+}
status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
{
@@ -276,8 +363,10 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
mRecordThreads.valueAt(i)->dump(fd, args);
}
- if (mAudioHardware) {
- mAudioHardware->dumpState(fd, args);
+ // dump all hardware devs
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ dev->dump(dev, fd);
}
if (locked) mLock.unlock();
}
@@ -308,7 +397,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
status_t lStatus;
int lSessionId;
- if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
+ if (streamType >= AUDIO_STREAM_CNT) {
LOGE("invalid stream type");
lStatus = BAD_VALUE;
goto Exit;
@@ -334,7 +423,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
}
LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
- if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
if (mPlaybackThreads.keyAt(i) != output) {
@@ -453,7 +542,7 @@ status_t AudioFlinger::setMasterVolume(float value)
{ // scope for the lock
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
+ if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
value = 1.0f;
}
mHardwareStatus = AUDIO_HW_IDLE;
@@ -475,7 +564,7 @@ status_t AudioFlinger::setMode(int mode)
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
+ if ((mode < 0) || (mode >= AUDIO_MODE_CNT)) {
LOGW("Illegal value: setMode(%d)", mode);
return BAD_VALUE;
}
@@ -483,7 +572,7 @@ status_t AudioFlinger::setMode(int mode)
{ // scope for the lock
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MODE;
- ret = mAudioHardware->setMode(mode);
+ ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -506,16 +595,16 @@ status_t AudioFlinger::setMicMute(bool state)
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
- status_t ret = mAudioHardware->setMicMute(state);
+ status_t ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
}
bool AudioFlinger::getMicMute() const
{
- bool state = AudioSystem::MODE_INVALID;
+ bool state = AUDIO_MODE_INVALID;
mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
- mAudioHardware->getMicMute(&state);
+ mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
mHardwareStatus = AUDIO_HW_IDLE;
return state;
}
@@ -552,7 +641,7 @@ status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
return PERMISSION_DENIED;
}
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
@@ -585,8 +674,8 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted)
return PERMISSION_DENIED;
}
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
- uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
+ if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT ||
+ uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
return BAD_VALUE;
}
@@ -600,7 +689,7 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted)
float AudioFlinger::streamVolume(int stream, int output) const
{
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || uint32_t(stream) >= AUDIO_STREAM_CNT) {
return 0.0f;
}
@@ -621,7 +710,7 @@ float AudioFlinger::streamVolume(int stream, int output) const
bool AudioFlinger::streamMute(int stream) const
{
- if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || stream >= (int)AUDIO_STREAM_CNT) {
return true;
}
@@ -643,9 +732,14 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
if (ioHandle == 0) {
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_SET_PARAMETER;
- result = mAudioHardware->setParameters(keyValuePairs);
+ status_t final_result = NO_ERROR;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ result = dev->set_parameters(dev, keyValuePairs.string());
+ final_result = result ?: final_result;
+ }
mHardwareStatus = AUDIO_HW_IDLE;
- return result;
+ return final_result;
}
// hold a strong ref on thread in case closeOutput() or closeInput() is called
@@ -671,7 +765,15 @@ String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
if (ioHandle == 0) {
- return mAudioHardware->getParameters(keys);
+ String8 out_s8;
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ char *s = dev->get_parameters(dev, keys.string());
+ out_s8 += String8(s);
+ free(s);
+ }
+ return out_s8;
}
Mutex::Autolock _l(mLock);
@@ -689,7 +791,7 @@ String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
{
- return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
+ return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
}
unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
@@ -716,7 +818,7 @@ status_t AudioFlinger::setVoiceVolume(float value)
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
- status_t ret = mAudioHardware->setVoiceVolume(value);
+ status_t ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
@@ -967,7 +1069,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
mMasterVolume = mAudioFlinger->masterVolume();
mMasterMute = mAudioFlinger->masterMute();
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+ for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
}
@@ -1130,12 +1232,12 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
// conflicts will happen when tracks are moved from one output to another by audio policy
// manager
uint32_t strategy =
- AudioSystem::getStrategyForStream((AudioSystem::stream_type)streamType);
+ AudioSystem::getStrategyForStream((audio_stream_type_t)streamType);
for (size_t i = 0; i < mTracks.size(); ++i) {
sp<Track> t = mTracks[i];
if (t != 0) {
if (sessionId == t->sessionId() &&
- strategy != AudioSystem::getStrategyForStream((AudioSystem::stream_type)t->type())) {
+ strategy != AudioSystem::getStrategyForStream((audio_stream_type_t)t->type())) {
lStatus = BAD_VALUE;
goto Exit;
}
@@ -1154,7 +1256,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
if (chain != 0) {
LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
track->setMainBuffer(chain->inBuffer());
- chain->setStrategy(AudioSystem::getStrategyForStream((AudioSystem::stream_type)track->type()));
+ chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
}
}
lStatus = NO_ERROR;
@@ -1169,7 +1271,7 @@ Exit:
uint32_t AudioFlinger::PlaybackThread::latency() const
{
if (mOutput) {
- return mOutput->latency();
+ return mOutput->stream->get_latency(mOutput->stream);
}
else {
return 0;
@@ -1263,7 +1365,13 @@ void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
{
- return mOutput->getParameters(keys);
+ String8 out_s8;
+ char *s;
+
+ s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
+ out_s8 = String8(s);
+ free(s);
+ return out_s8;
}
// destroyTrack_l() must be called with AudioFlinger::mLock held
@@ -1295,12 +1403,12 @@ void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
void AudioFlinger::PlaybackThread::readOutputParameters()
{
- mSampleRate = mOutput->sampleRate();
- mChannels = mOutput->channels();
- mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
- mFormat = mOutput->format();
- mFrameSize = (uint16_t)mOutput->frameSize();
- mFrameCount = mOutput->bufferSize() / mFrameSize;
+ mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
+ mChannels = mOutput->stream->common.get_channels(&mOutput->stream->common);
+ mChannelCount = (uint16_t)popcount(mChannels);
+ mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
+ mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
+ mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
// FIXME - Current mixer implementation only supports stereo output: Always
// Allocate a stereo buffer even if HW output is mono.
@@ -1328,9 +1436,9 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, ui
if (mOutput == 0) {
return INVALID_OPERATION;
}
- *halFrames = mBytesWritten/mOutput->frameSize();
+ *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
- return mOutput->getRenderPosition(dspFrames);
+ return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
}
uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
@@ -1355,19 +1463,19 @@ uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
{
- // session AudioSystem::SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
+ // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
// it is moved to correct output by audio policy manager when A2DP is connected or disconnected
- if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
- return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+ return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
}
for (size_t i = 0; i < mTracks.size(); i++) {
sp<Track> track = mTracks[i];
if (sessionId == track->sessionId() &&
!(track->mCblk->flags & CBLK_INVALID_MSK)) {
- return AudioSystem::getStrategyForStream((AudioSystem::stream_type) track->type());
+ return AudioSystem::getStrategyForStream((audio_stream_type_t) track->type());
}
}
- return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+ return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
}
sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
@@ -1460,7 +1568,7 @@ bool AudioFlinger::MixerThread::threadLoop()
mSuspended) {
if (!mStandby) {
LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
}
@@ -1537,7 +1645,7 @@ bool AudioFlinger::MixerThread::threadLoop()
mInWrite = true;
mBytesWritten += mixBufferSize;
- int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+ int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
@@ -1572,7 +1680,7 @@ bool AudioFlinger::MixerThread::threadLoop()
}
if (!mStandby) {
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
}
LOGV("MixerThread %p exiting", this);
@@ -1596,7 +1704,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
masterVolume = 0;
}
// Delegate master volume control to effect in output mix effect chain if needed
- sp<EffectChain> chain = getEffectChain_l(AudioSystem::SESSION_OUTPUT_MIX);
+ sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (chain != 0) {
uint32_t v = (uint32_t)(masterVolume * (1 << 24));
chain->setVolume_l(&v, &v);
@@ -1738,7 +1846,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun
- cblk->flags |= CBLK_DISABLED_ON;
+ android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
} else if (mixerStatus != MIXER_TRACKS_READY) {
mixerStatus = MIXER_TRACKS_ENABLED;
}
@@ -1787,10 +1895,8 @@ void AudioFlinger::MixerThread::invalidateTracks(int streamType)
for (size_t i = 0; i < size; i++) {
sp<Track> t = mTracks[i];
if (t->type() == streamType) {
- t->mCblk->lock.lock();
- t->mCblk->flags |= CBLK_INVALID_ON;
+ android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
t->mCblk->cv.signal();
- t->mCblk->lock.unlock();
}
}
}
@@ -1824,14 +1930,14 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
- if (value != AudioSystem::PCM_16_BIT) {
+ if (value != AUDIO_FORMAT_PCM_16_BIT) {
status = BAD_VALUE;
} else {
reconfig = true;
}
}
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- if (value != AudioSystem::CHANNEL_OUT_STEREO) {
+ if (value != AUDIO_CHANNEL_OUT_STEREO) {
status = BAD_VALUE;
} else {
reconfig = true;
@@ -1853,12 +1959,12 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
if (mDevice != value) {
uint32_t params = 0;
// check whether speaker is on
- if (value & AudioSystem::DEVICE_OUT_SPEAKER) {
+ if (value & AUDIO_DEVICE_OUT_SPEAKER) {
params |= IMediaPlayerService::kBatteryDataSpeakerOn;
}
int deviceWithoutSpeaker
- = AudioSystem::DEVICE_OUT_ALL & ~AudioSystem::DEVICE_OUT_SPEAKER;
+ = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
// check if any other device (except speaker) is on
if (value & deviceWithoutSpeaker ) {
params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
@@ -1878,12 +1984,14 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
}
if (status == NO_ERROR) {
- status = mOutput->setParameters(keyValuePair);
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
if (!mStandby && status == INVALID_OPERATION) {
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
- status = mOutput->setParameters(keyValuePair);
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
}
if (status == NO_ERROR && reconfig) {
delete mAudioMixer;
@@ -1927,7 +2035,7 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>
uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
{
- return (uint32_t)(mOutput->latency() * 1000) / 2;
+ return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
}
uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
@@ -1977,12 +2085,12 @@ int32_t mul(int16_t in, int16_t v)
void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
{
// Do not apply volume on compressed audio
- if (!AudioSystem::isLinearPCM(mFormat)) {
+ if (!audio_is_linear_pcm(mFormat)) {
return;
}
// convert to signed 16 bit before volume calculation
- if (mFormat == AudioSystem::PCM_8_BIT) {
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
size_t count = mFrameCount * mChannelCount;
uint8_t *src = (uint8_t *)mMixBuffer + count-1;
int16_t *dst = mMixBuffer + count-1;
@@ -2035,7 +2143,7 @@ void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t ri
}
// convert back to unsigned 8 bit after volume calculation
- if (mFormat == AudioSystem::PCM_8_BIT) {
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
size_t count = mFrameCount * mChannelCount;
int16_t *src = mMixBuffer;
uint8_t *dst = (uint8_t *)mMixBuffer;
@@ -2091,7 +2199,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
// wait until we have something to do...
if (!mStandby) {
LOGV("Audio hardware entering standby, mixer %p\n", this);
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
}
@@ -2176,7 +2284,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
// If audio HAL implements volume control,
// force software volume to nominal value
- if (mOutput->setVolume(left, right) == NO_ERROR) {
+ if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
left = 1.0f;
right = 1.0f;
}
@@ -2277,7 +2385,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
} else {
sleepTime = idleSleepTime;
}
- } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
+ } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
memset (mMixBuffer, 0, mFrameCount * mFrameSize);
sleepTime = 0;
}
@@ -2299,7 +2407,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
mLastWriteTime = systemTime();
mInWrite = true;
mBytesWritten += mixBufferSize;
- int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+ int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
@@ -2321,7 +2429,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
}
if (!mStandby) {
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
}
LOGV("DirectOutputThread %p exiting", this);
@@ -2361,12 +2469,14 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
}
}
if (status == NO_ERROR) {
- status = mOutput->setParameters(keyValuePair);
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
if (!mStandby && status == INVALID_OPERATION) {
- mOutput->standby();
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
- status = mOutput->setParameters(keyValuePair);
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
}
if (status == NO_ERROR && reconfig) {
readOutputParameters();
@@ -2386,8 +2496,8 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
{
uint32_t time;
- if (AudioSystem::isLinearPCM(mFormat)) {
- time = (uint32_t)(mOutput->latency() * 1000) / 2;
+ if (audio_is_linear_pcm(mFormat)) {
+ time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
} else {
time = 10000;
}
@@ -2397,7 +2507,7 @@ uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
{
uint32_t time;
- if (AudioSystem::isLinearPCM(mFormat)) {
+ if (audio_is_linear_pcm(mFormat)) {
time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
} else {
time = 10000;
@@ -2408,7 +2518,7 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
{
uint32_t time;
- if (AudioSystem::isLinearPCM(mFormat)) {
+ if (audio_is_linear_pcm(mFormat)) {
time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
} else {
time = 10000;
@@ -2589,7 +2699,7 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
mChannelCount,
frameCount);
if (outputTrack->cblk() != NULL) {
- thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
+ thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
mOutputTracks.add(outputTrack);
LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
updateWaitTime();
@@ -2834,7 +2944,7 @@ AudioFlinger::PlaybackThread::Track::Track(
mStreamType = streamType;
// NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
// 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
- mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
+ mCblk->frameSize = audio_is_linear_pcm(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
}
}
@@ -2865,7 +2975,7 @@ void AudioFlinger::PlaybackThread::Track::destroy()
if (!isOutputTrack()) {
if (mState == ACTIVE || mState == RESUMING) {
AudioSystem::stopOutput(thread->id(),
- (AudioSystem::stream_type)mStreamType,
+ (audio_stream_type_t)mStreamType,
mSessionId);
// to track the speaker usage
@@ -2949,7 +3059,7 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
if (mCblk->framesReady() >= mCblk->frameCount ||
(mCblk->flags & CBLK_FORCEREADY_MSK)) {
mFillingUpStatus = FS_FILLED;
- mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+ android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
return true;
}
return false;
@@ -2977,7 +3087,7 @@ status_t AudioFlinger::PlaybackThread::Track::start()
if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
thread->mLock.unlock();
status = AudioSystem::startOutput(thread->id(),
- (AudioSystem::stream_type)mStreamType,
+ (audio_stream_type_t)mStreamType,
mSessionId);
thread->mLock.lock();
@@ -3017,7 +3127,7 @@ void AudioFlinger::PlaybackThread::Track::stop()
if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
thread->mLock.unlock();
AudioSystem::stopOutput(thread->id(),
- (AudioSystem::stream_type)mStreamType,
+ (audio_stream_type_t)mStreamType,
mSessionId);
thread->mLock.lock();
@@ -3039,7 +3149,7 @@ void AudioFlinger::PlaybackThread::Track::pause()
if (!isOutputTrack()) {
thread->mLock.unlock();
AudioSystem::stopOutput(thread->id(),
- (AudioSystem::stream_type)mStreamType,
+ (audio_stream_type_t)mStreamType,
mSessionId);
thread->mLock.lock();
@@ -3063,14 +3173,12 @@ void AudioFlinger::PlaybackThread::Track::flush()
// STOPPED state
mState = STOPPED;
- mCblk->lock.lock();
- // NOTE: reset() will reset cblk->user and cblk->server with
- // the risk that at the same time, the AudioMixer is trying to read
- // data. In this case, getNextBuffer() would return a NULL pointer
- // as audio buffer => the AudioMixer code MUST always test that pointer
- // returned by getNextBuffer() is not NULL!
- reset();
- mCblk->lock.unlock();
+ // do not reset the track if it is still in the process of being stopped or paused.
+ // this will be done by prepareTracks_l() when the track is stopped.
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ reset();
+ }
}
}
@@ -3082,8 +3190,8 @@ void AudioFlinger::PlaybackThread::Track::reset()
TrackBase::reset();
// Force underrun condition to avoid false underrun callback until first data is
// written to buffer
- mCblk->flags |= CBLK_UNDERRUN_ON;
- mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+ android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
+ android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
mFillingUpStatus = FS_FILLING;
mResetDone = true;
}
@@ -3135,9 +3243,9 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
{
if (mCblk != NULL) {
LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
- if (format == AudioSystem::PCM_16_BIT) {
+ if (format == AUDIO_FORMAT_PCM_16_BIT) {
mCblk->frameSize = channelCount * sizeof(int16_t);
- } else if (format == AudioSystem::PCM_8_BIT) {
+ } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
mCblk->frameSize = channelCount * sizeof(int8_t);
} else {
mCblk->frameSize = sizeof(int8_t);
@@ -3212,7 +3320,7 @@ void AudioFlinger::RecordThread::RecordTrack::stop()
TrackBase::reset();
// Force overerrun condition to avoid false overrun callback until first data is
// read from buffer
- mCblk->flags |= CBLK_UNDERRUN_ON;
+ android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
}
}
@@ -3240,7 +3348,7 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
int format,
int channelCount,
int frameCount)
- : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL, 0),
+ : Track(thread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelCount, frameCount, NULL, 0),
mActive(false), mSourceThread(sourceThread)
{
@@ -3612,7 +3720,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
}
// If no audio session id is provided, create one here
- if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
lSessionId = *sessionId;
} else {
lSessionId = nextUniqueId_l();
@@ -3682,7 +3790,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, A
ThreadBase(audioFlinger, id),
mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{
- mReqChannelCount = AudioSystem::popCount(channels);
+ mReqChannelCount = popcount(channels);
mReqSampleRate = sampleRate;
readInputParameters();
}
@@ -3724,7 +3832,7 @@ bool AudioFlinger::RecordThread::threadLoop()
checkForNewParameters_l();
if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
if (!mStandby) {
- mInput->standby();
+ mInput->stream->common.standby(&mInput->stream->common);
mStandby = true;
}
@@ -3739,7 +3847,7 @@ bool AudioFlinger::RecordThread::threadLoop()
if (mActiveTrack != 0) {
if (mActiveTrack->mState == TrackBase::PAUSING) {
if (!mStandby) {
- mInput->standby();
+ mInput->stream->common.standby(&mInput->stream->common);
mStandby = true;
}
mActiveTrack.clear();
@@ -3784,7 +3892,7 @@ bool AudioFlinger::RecordThread::threadLoop()
mRsmpInIndex += framesIn;
framesOut -= framesIn;
if ((int)mChannelCount == mReqChannelCount ||
- mFormat != AudioSystem::PCM_16_BIT) {
+ mFormat != AUDIO_FORMAT_PCM_16_BIT) {
memcpy(dst, src, framesIn * mFrameSize);
} else {
int16_t *src16 = (int16_t *)src;
@@ -3804,11 +3912,11 @@ bool AudioFlinger::RecordThread::threadLoop()
}
if (framesOut && mFrameCount == mRsmpInIndex) {
if (framesOut == mFrameCount &&
- ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
- mBytesRead = mInput->read(buffer.raw, mInputBytes);
+ ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
+ mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
framesOut = 0;
} else {
- mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
mRsmpInIndex = 0;
}
if (mBytesRead < 0) {
@@ -3816,7 +3924,7 @@ bool AudioFlinger::RecordThread::threadLoop()
if (mActiveTrack->mState == TrackBase::ACTIVE) {
// Force input into standby so that it tries to
// recover at next read attempt
- mInput->standby();
+ mInput->stream->common.standby(&mInput->stream->common);
usleep(5000);
}
mRsmpInIndex = mFrameCount;
@@ -3871,7 +3979,7 @@ bool AudioFlinger::RecordThread::threadLoop()
}
if (!mStandby) {
- mInput->standby();
+ mInput->stream->common.standby(&mInput->stream->common);
}
mActiveTrack.clear();
@@ -4003,13 +4111,13 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer*
int channelCount;
if (framesReady == 0) {
- mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
if (mBytesRead < 0) {
LOGE("RecordThread::getNextBuffer() Error reading audio input");
if (mActiveTrack->mState == TrackBase::ACTIVE) {
// Force input into standby so that it tries to
// recover at next read attempt
- mInput->standby();
+ mInput->stream->common.standby(&mInput->stream->common);
usleep(5000);
}
buffer->raw = 0;
@@ -4062,7 +4170,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- reqChannelCount = AudioSystem::popCount(value);
+ reqChannelCount = popcount(value);
reconfig = true;
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
@@ -4076,16 +4184,18 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
}
}
if (status == NO_ERROR) {
- status = mInput->setParameters(keyValuePair);
+ status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
if (status == INVALID_OPERATION) {
- mInput->standby();
- status = mInput->setParameters(keyValuePair);
+ mInput->stream->common.standby(&mInput->stream->common);
+ status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
}
if (reconfig) {
if (status == BAD_VALUE &&
- reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
- ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
- (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
+ reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
+ reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
+ ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
+ (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
+ (reqChannelCount < 3)) {
status = NO_ERROR;
}
if (status == NO_ERROR) {
@@ -4106,7 +4216,13 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l()
String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
{
- return mInput->getParameters(keys);
+ char *s;
+ String8 out_s8;
+
+ s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
+ out_s8 = String8(s);
+ free(s);
+ return out_s8;
}
void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
@@ -4138,12 +4254,12 @@ void AudioFlinger::RecordThread::readInputParameters()
if (mResampler) delete mResampler;
mResampler = 0;
- mSampleRate = mInput->sampleRate();
- mChannels = mInput->channels();
- mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
- mFormat = mInput->format();
- mFrameSize = (uint16_t)mInput->frameSize();
- mInputBytes = mInput->bufferSize();
+ mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
+ mChannels = mInput->stream->common.get_channels(&mInput->stream->common);
+ mChannelCount = (uint16_t)popcount(mChannels);
+ mFormat = mInput->stream->common.get_format(&mInput->stream->common);
+ mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
+ mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
mFrameCount = mInputBytes / mFrameSize;
mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
@@ -4173,7 +4289,7 @@ void AudioFlinger::RecordThread::readInputParameters()
unsigned int AudioFlinger::RecordThread::getInputFramesLost()
{
- return mInput->getInputFramesLost();
+ return mInput->stream->get_input_frames_lost(mInput->stream);
}
// ----------------------------------------------------------------------------
@@ -4192,6 +4308,8 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
uint32_t format = pFormat ? *pFormat : 0;
uint32_t channels = pChannels ? *pChannels : 0;
uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+ audio_stream_out_t *outStream;
+ audio_hw_device_t *outHwDev;
LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
pDevices ? *pDevices : 0,
@@ -4203,26 +4321,30 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
if (pDevices == NULL || *pDevices == 0) {
return 0;
}
+
Mutex::Autolock _l(mLock);
- AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status);
+ outHwDev = findSuitableHwDev_l(*pDevices);
+ if (outHwDev == NULL)
+ return 0;
+
+ status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate, &outStream);
LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
- output,
+ outStream,
samplingRate,
format,
channels,
status);
mHardwareStatus = AUDIO_HW_IDLE;
- if (output != 0) {
+ if (outStream != NULL) {
+ AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
int id = nextUniqueId_l();
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format != AudioSystem::PCM_16_BIT) ||
- (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
+ (format != AUDIO_FORMAT_PCM_16_BIT) ||
+ (channels != AUDIO_CHANNEL_OUT_STEREO)) {
thread = new DirectOutputThread(this, output, id, *pDevices);
LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
} else {
@@ -4293,7 +4415,9 @@ status_t AudioFlinger::closeOutput(int output)
thread->exit();
if (thread->type() != PlaybackThread::DUPLICATING) {
- mAudioHardware->closeOutputStream(thread->getOutput());
+ AudioStreamOut *out = thread->getOutput();
+ out->hwDev->close_output_stream(out->hwDev, out->stream);
+ delete out;
}
return NO_ERROR;
}
@@ -4343,20 +4467,25 @@ int AudioFlinger::openInput(uint32_t *pDevices,
uint32_t reqSamplingRate = samplingRate;
uint32_t reqFormat = format;
uint32_t reqChannels = channels;
+ audio_stream_in_t *inStream;
+ audio_hw_device_t *inHwDev;
if (pDevices == NULL || *pDevices == 0) {
return 0;
}
+
Mutex::Autolock _l(mLock);
- AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status,
- (AudioSystem::audio_in_acoustics)acoustics);
+ inHwDev = findSuitableHwDev_l(*pDevices);
+ if (inHwDev == NULL)
+ return 0;
+
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate,
+ (audio_in_acoustics_t)acoustics,
+ &inStream);
LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
- input,
+ inStream,
samplingRate,
format,
channels,
@@ -4366,20 +4495,20 @@ int AudioFlinger::openInput(uint32_t *pDevices,
// If the input could not be opened with the requested parameters and we can handle the conversion internally,
// try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
// or stereo to mono conversions on 16 bit PCM inputs.
- if (input == 0 && status == BAD_VALUE &&
- reqFormat == format && format == AudioSystem::PCM_16_BIT &&
+ if (inStream == NULL && status == BAD_VALUE &&
+ reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
(samplingRate <= 2 * reqSamplingRate) &&
- (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
+ (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
LOGV("openInput() reopening with proposed sampling rate and channels");
- input = mAudioHardware->openInputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status,
- (AudioSystem::audio_in_acoustics)acoustics);
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate,
+ (audio_in_acoustics_t)acoustics,
+ &inStream);
}
- if (input != 0) {
+ if (inStream != NULL) {
+ AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
+
int id = nextUniqueId_l();
// Start record thread
thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
@@ -4389,7 +4518,7 @@ int AudioFlinger::openInput(uint32_t *pDevices,
if (pFormat) *pFormat = format;
if (pChannels) *pChannels = reqChannels;
- input->standby();
+ input->stream->common.standby(&input->stream->common);
// notify client processes of the new input creation
thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
@@ -4418,7 +4547,9 @@ status_t AudioFlinger::closeInput(int input)
}
thread->exit();
- mAudioHardware->closeInputStream(thread->getInput());
+ AudioStreamIn *in = thread->getInput();
+ in->hwDev->close_input_stream(in->hwDev, in->stream);
+ delete in;
return NO_ERROR;
}
@@ -4572,14 +4703,14 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
// check audio settings permission for global effects
- if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
- // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
+ // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
// that can only be created by audio policy manager (running in same process)
- if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE && getpid() != pid) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@@ -4593,12 +4724,12 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
if (output == 0) {
- if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
// output must be specified by AudioPolicyManager when using session
- // AudioSystem::SESSION_OUTPUT_STAGE
+ // AUDIO_SESSION_OUTPUT_STAGE
lStatus = BAD_VALUE;
goto Exit;
- } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
+ } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
// if the output returned by getOutputForEffect() is removed before we lock the
// mutex below, the call to checkPlaybackThread_l(output) below will detect it
// and we will exit safely
@@ -4646,7 +4777,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
// an auxiliary version of this effect type is available
found = true;
memcpy(&d, &desc, sizeof(effect_descriptor_t));
- if (sessionId != AudioSystem::SESSION_OUTPUT_MIX ||
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
(desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
break;
}
@@ -4659,14 +4790,14 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
}
// For same effect type, chose auxiliary version over insert version if
// connect to output mix (Compliance to OpenSL ES)
- if (sessionId == AudioSystem::SESSION_OUTPUT_MIX &&
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
(d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
memcpy(&desc, &d, sizeof(effect_descriptor_t));
}
}
// Do not allow auxiliary effects on a session different from 0 (output mix)
- if (sessionId != AudioSystem::SESSION_OUTPUT_MIX &&
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
(desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
lStatus = INVALID_OPERATION;
goto Exit;
@@ -4839,7 +4970,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
// Do not allow auxiliary effect on session other than 0
if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
- sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+ sessionId != AUDIO_SESSION_OUTPUT_MIX) {
LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
desc->name, sessionId);
lStatus = BAD_VALUE;
@@ -4848,7 +4979,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
// Do not allow effects with session ID 0 on direct output or duplicating threads
// TODO: add rule for hw accelerated effects on direct outputs with non PCM format
- if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && mType != MIXER) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
desc->name, sessionId);
lStatus = BAD_VALUE;
@@ -5035,13 +5166,13 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c
chain->setInBuffer(buffer, ownsBuffer);
chain->setOutBuffer(mMixBuffer);
- // Effect chain for session AudioSystem::SESSION_OUTPUT_STAGE is inserted at end of effect
+ // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
// chains list in order to be processed last as it contains output stage effects
- // Effect chain for session AudioSystem::SESSION_OUTPUT_MIX is inserted before
- // session AudioSystem::SESSION_OUTPUT_STAGE to be processed
+ // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
+ // session AUDIO_SESSION_OUTPUT_STAGE to be processed
// after track specific effects and before output stage
- // It is therefore mandatory that AudioSystem::SESSION_OUTPUT_MIX == 0 and
- // that AudioSystem::SESSION_OUTPUT_STAGE < AudioSystem::SESSION_OUTPUT_MIX
+ // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
+ // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
// Effect chain for other sessions are inserted at beginning of effect
// chains list to be processed before output mix effects. Relative order between other
// sessions is not important
@@ -5121,8 +5252,8 @@ status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
if (EffectId == 0) {
track->setAuxBuffer(0, NULL);
} else {
- // Auxiliary effects are always in audio session AudioSystem::SESSION_OUTPUT_MIX
- sp<EffectModule> effect = getEffect_l(AudioSystem::SESSION_OUTPUT_MIX, EffectId);
+ // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
+ sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
if (effect != 0) {
if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
@@ -5406,7 +5537,7 @@ status_t AudioFlinger::EffectModule::configure()
mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
// Insert effect:
- // - in session AudioSystem::SESSION_OUTPUT_MIX or AudioSystem::SESSION_OUTPUT_STAGE,
+ // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
// always overwrites output buffer: input buffer == output buffer
// - in other sessions:
// last effect in the chain accumulates in output buffer: input buffer != output buffer
@@ -5687,17 +5818,17 @@ status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
- DEVICE_EARPIECE, // AudioSystem::DEVICE_OUT_EARPIECE
- DEVICE_SPEAKER, // AudioSystem::DEVICE_OUT_SPEAKER
- DEVICE_WIRED_HEADSET, // case AudioSystem::DEVICE_OUT_WIRED_HEADSET
- DEVICE_WIRED_HEADPHONE, // AudioSystem::DEVICE_OUT_WIRED_HEADPHONE
- DEVICE_BLUETOOTH_SCO, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO
- DEVICE_BLUETOOTH_SCO_HEADSET, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET
- DEVICE_BLUETOOTH_SCO_CARKIT, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT
- DEVICE_BLUETOOTH_A2DP, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP
- DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
- DEVICE_BLUETOOTH_A2DP_SPEAKER, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
- DEVICE_AUX_DIGITAL // AudioSystem::DEVICE_OUT_AUX_DIGITAL
+ DEVICE_EARPIECE, // AUDIO_DEVICE_OUT_EARPIECE
+ DEVICE_SPEAKER, // AUDIO_DEVICE_OUT_SPEAKER
+ DEVICE_WIRED_HEADSET, // case AUDIO_DEVICE_OUT_WIRED_HEADSET
+ DEVICE_WIRED_HEADPHONE, // AUDIO_DEVICE_OUT_WIRED_HEADPHONE
+ DEVICE_BLUETOOTH_SCO, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO
+ DEVICE_BLUETOOTH_SCO_HEADSET, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
+ DEVICE_BLUETOOTH_SCO_CARKIT, // AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT
+ DEVICE_BLUETOOTH_A2DP, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
+ DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+ DEVICE_BLUETOOTH_A2DP_SPEAKER, // AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
+ DEVICE_AUX_DIGITAL // AUDIO_DEVICE_OUT_AUX_DIGITAL
};
uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
@@ -5707,7 +5838,7 @@ uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t devic
const uint32_t i = 31 - __builtin_clz(device);
device &= ~(1 << i);
if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
- LOGE("device convertion error for AudioSystem device 0x%08x", device);
+ LOGE("device conversion error for AudioSystem device 0x%08x", device);
return 0;
}
deviceOut |= (uint32_t)sDeviceConvTable[i];
@@ -5717,10 +5848,10 @@ uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t devic
// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
- AUDIO_MODE_NORMAL, // AudioSystem::MODE_NORMAL
- AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
- AUDIO_MODE_IN_CALL, // AudioSystem::MODE_IN_CALL
- AUDIO_MODE_IN_CALL // AudioSystem::MODE_IN_COMMUNICATION, same conversion as for MODE_IN_CALL
+ AUDIO_EFFECT_MODE_NORMAL, // AUDIO_MODE_NORMAL
+ AUDIO_EFFECT_MODE_RINGTONE, // AUDIO_MODE_RINGTONE
+ AUDIO_EFFECT_MODE_IN_CALL, // AUDIO_MODE_IN_CALL
+ AUDIO_EFFECT_MODE_IN_CALL // AUDIO_MODE_IN_COMMUNICATION, same conversion as for AUDIO_MODE_IN_CALL
};
int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
@@ -6030,7 +6161,7 @@ AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
{
- mStrategy = AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+ mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
}
AudioFlinger::EffectChain::~EffectChain()
@@ -6081,8 +6212,8 @@ void AudioFlinger::EffectChain::process_l()
return;
}
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- bool isGlobalSession = (mSessionId == AudioSystem::SESSION_OUTPUT_MIX) ||
- (mSessionId == AudioSystem::SESSION_OUTPUT_STAGE);
+ bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
+ (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
bool tracksOnSession = false;
if (!isGlobalSession) {
tracksOnSession =
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ec3d202..22e5116 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -32,12 +32,14 @@
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
#include <utils/Vector.h>
#include <binder/BinderService.h>
#include <binder/MemoryDealer.h>
-#include <hardware_legacy/AudioHardwareInterface.h>
+#include <hardware/audio.h>
+#include <hardware/audio_hal.h>
#include "AudioBufferProvider.h"
@@ -49,7 +51,6 @@ class AudioMixer;
class AudioBuffer;
class AudioResampler;
-
// ----------------------------------------------------------------------------
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@@ -211,6 +212,9 @@ private:
AudioFlinger();
virtual ~AudioFlinger();
+ status_t initCheck() const;
+ virtual void onFirstRef();
+ audio_hw_device_t* findSuitableHwDev_l(uint32_t devices);
// Internal dump utilites.
status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -268,6 +272,8 @@ private:
class EffectModule;
class EffectHandle;
class EffectChain;
+ struct AudioStreamOut;
+ struct AudioStreamIn;
class ThreadBase : public Thread {
public:
@@ -495,7 +501,7 @@ private:
void reset();
bool isOutputTrack() const {
- return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
+ return (mStreamType == AUDIO_STREAM_CNT);
}
// we don't really need a lock for these
@@ -689,7 +695,7 @@ private:
SortedVector< sp<Track> > mTracks;
// mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
- stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1];
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
AudioStreamOut* mOutput;
float mMasterVolume;
nsecs_t mLastWriteTime;
@@ -1159,21 +1165,37 @@ private:
uint32_t mStrategy; // strategy for this effect chain
};
+ struct AudioStreamOut {
+ audio_hw_device_t *hwDev;
+ audio_stream_out_t *stream;
+
+ AudioStreamOut(audio_hw_device_t *dev, audio_stream_out_t *out) :
+ hwDev(dev), stream(out) {}
+ };
+
+ struct AudioStreamIn {
+ audio_hw_device_t *hwDev;
+ audio_stream_in_t *stream;
+
+ AudioStreamIn(audio_hw_device_t *dev, audio_stream_in_t *in) :
+ hwDev(dev), stream(in) {}
+ };
+
friend class RecordThread;
friend class PlaybackThread;
-
mutable Mutex mLock;
DefaultKeyedVector< pid_t, wp<Client> > mClients;
mutable Mutex mHardwareLock;
- AudioHardwareInterface* mAudioHardware;
+ audio_hw_device_t* mPrimaryHardwareDev;
+ Vector<audio_hw_device_t*> mAudioHwDevs;
mutable int mHardwareStatus;
DefaultKeyedVector< int, sp<PlaybackThread> > mPlaybackThreads;
- PlaybackThread::stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+ PlaybackThread::stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
float mMasterVolume;
bool mMasterMute;
@@ -1185,6 +1207,7 @@ private:
};
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/services/audioflinger/AudioHardwareGeneric.cpp b/services/audioflinger/AudioHardwareGeneric.cpp
deleted file mode 100644
index d63c031..0000000
--- a/services/audioflinger/AudioHardwareGeneric.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-**
-** Copyright 2007, 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 <stdint.h>
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sched.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#define LOG_TAG "AudioHardware"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareGeneric.h"
-#include <media/AudioRecord.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-static char const * const kAudioDeviceName = "/dev/eac";
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareGeneric::AudioHardwareGeneric()
- : mOutput(0), mInput(0), mFd(-1), mMicMute(false)
-{
- mFd = ::open(kAudioDeviceName, O_RDWR);
-}
-
-AudioHardwareGeneric::~AudioHardwareGeneric()
-{
- if (mFd >= 0) ::close(mFd);
- closeOutputStream((AudioStreamOut *)mOutput);
- closeInputStream((AudioStreamIn *)mInput);
-}
-
-status_t AudioHardwareGeneric::initCheck()
-{
- if (mFd >= 0) {
- if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
- return NO_ERROR;
- }
- return NO_INIT;
-}
-
-AudioStreamOut* AudioHardwareGeneric::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AutoMutex lock(mLock);
-
- // only one output stream allowed
- if (mOutput) {
- if (status) {
- *status = INVALID_OPERATION;
- }
- return 0;
- }
-
- // create new output stream
- AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
- status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR) {
- mOutput = out;
- } else {
- delete out;
- }
- return mOutput;
-}
-
-void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
- if (mOutput && out == mOutput) {
- delete mOutput;
- mOutput = 0;
- }
-}
-
-AudioStreamIn* AudioHardwareGeneric::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
- status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- // check for valid input source
- if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
- return 0;
- }
-
- AutoMutex lock(mLock);
-
- // only one input stream allowed
- if (mInput) {
- if (status) {
- *status = INVALID_OPERATION;
- }
- return 0;
- }
-
- // create new output stream
- AudioStreamInGeneric* in = new AudioStreamInGeneric();
- status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR) {
- mInput = in;
- } else {
- delete in;
- }
- return mInput;
-}
-
-void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
- if (mInput && in == mInput) {
- delete mInput;
- mInput = 0;
- }
-}
-
-status_t AudioHardwareGeneric::setVoiceVolume(float v)
-{
- // Implement: set voice volume
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::setMasterVolume(float v)
-{
- // Implement: set master volume
- // return error - software mixer will handle it
- return INVALID_OPERATION;
-}
-
-status_t AudioHardwareGeneric::setMicMute(bool state)
-{
- mMicMute = state;
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::getMicMute(bool* state)
-{
- *state = mMicMute;
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- result.append("AudioHardwareGeneric::dumpInternals\n");
- snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
-{
- dumpInternals(fd, args);
- if (mInput) {
- mInput->dump(fd, args);
- }
- if (mOutput) {
- mOutput->dump(fd, args);
- }
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamOutGeneric::set(
- AudioHardwareGeneric *hw,
- int fd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate)
-{
- int lFormat = pFormat ? *pFormat : 0;
- uint32_t lChannels = pChannels ? *pChannels : 0;
- uint32_t lRate = pRate ? *pRate : 0;
-
- // fix up defaults
- if (lFormat == 0) lFormat = format();
- if (lChannels == 0) lChannels = channels();
- if (lRate == 0) lRate = sampleRate();
-
- // check values
- if ((lFormat != format()) ||
- (lChannels != channels()) ||
- (lRate != sampleRate())) {
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- if (pFormat) *pFormat = lFormat;
- if (pChannels) *pChannels = lChannels;
- if (pRate) *pRate = lRate;
-
- mAudioHardware = hw;
- mFd = fd;
- mDevice = devices;
- return NO_ERROR;
-}
-
-AudioStreamOutGeneric::~AudioStreamOutGeneric()
-{
-}
-
-ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
-{
- Mutex::Autolock _l(mLock);
- return ssize_t(::write(mFd, buffer, bytes));
-}
-
-status_t AudioStreamOutGeneric::standby()
-{
- // Implement: audio hardware to standby mode
- return NO_ERROR;
-}
-
-status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 key = String8(AudioParameter::keyRouting);
- status_t status = NO_ERROR;
- int device;
- LOGV("setParameters() %s", keyValuePairs.string());
-
- if (param.getInt(key, device) == NO_ERROR) {
- mDevice = device;
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 AudioStreamOutGeneric::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8(AudioParameter::keyRouting);
-
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames)
-{
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-// record functions
-status_t AudioStreamInGeneric::set(
- AudioHardwareGeneric *hw,
- int fd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics)
-{
- if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
- LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
- // check values
- if ((*pFormat != format()) ||
- (*pChannels != channels()) ||
- (*pRate != sampleRate())) {
- LOGE("Error opening input channel");
- *pFormat = format();
- *pChannels = channels();
- *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- mAudioHardware = hw;
- mFd = fd;
- mDevice = devices;
- return NO_ERROR;
-}
-
-AudioStreamInGeneric::~AudioStreamInGeneric()
-{
-}
-
-ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
-{
- AutoMutex lock(mLock);
- if (mFd < 0) {
- LOGE("Attempt to read from unopened device");
- return NO_INIT;
- }
- return ::read(mFd, buffer, bytes);
-}
-
-status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 key = String8(AudioParameter::keyRouting);
- status_t status = NO_ERROR;
- int device;
- LOGV("setParameters() %s", keyValuePairs.string());
-
- if (param.getInt(key, device) == NO_ERROR) {
- mDevice = device;
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 AudioStreamInGeneric::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8(AudioParameter::keyRouting);
-
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/audioflinger/AudioHardwareGeneric.h b/services/audioflinger/AudioHardwareGeneric.h
deleted file mode 100644
index aa4e78d..0000000
--- a/services/audioflinger/AudioHardwareGeneric.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-**
-** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_GENERIC_H
-#define ANDROID_AUDIO_HARDWARE_GENERIC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class AudioHardwareGeneric;
-
-class AudioStreamOutGeneric : public AudioStreamOut {
-public:
- AudioStreamOutGeneric() : mAudioHardware(0), mFd(-1) {}
- virtual ~AudioStreamOutGeneric();
-
- virtual status_t set(
- AudioHardwareGeneric *hw,
- int mFd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate);
-
- virtual uint32_t sampleRate() const { return 44100; }
- virtual size_t bufferSize() const { return 4096; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return 20; }
- virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
-private:
- AudioHardwareGeneric *mAudioHardware;
- Mutex mLock;
- int mFd;
- uint32_t mDevice;
-};
-
-class AudioStreamInGeneric : public AudioStreamIn {
-public:
- AudioStreamInGeneric() : mAudioHardware(0), mFd(-1) {}
- virtual ~AudioStreamInGeneric();
-
- virtual status_t set(
- AudioHardwareGeneric *hw,
- int mFd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics);
-
- virtual uint32_t sampleRate() const { return 8000; }
- virtual size_t bufferSize() const { return 320; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_IN_MONO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual status_t setGain(float gain) { return INVALID_OPERATION; }
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t standby() { return NO_ERROR; }
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const { return 0; }
-
-private:
- AudioHardwareGeneric *mAudioHardware;
- Mutex mLock;
- int mFd;
- uint32_t mDevice;
-};
-
-
-class AudioHardwareGeneric : public AudioHardwareBase
-{
-public:
- AudioHardwareGeneric();
- virtual ~AudioHardwareGeneric();
- virtual status_t initCheck();
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- // mic mute
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool* state);
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
- void closeOutputStream(AudioStreamOutGeneric* out);
- void closeInputStream(AudioStreamInGeneric* in);
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
-private:
- status_t dumpInternals(int fd, const Vector<String16>& args);
-
- Mutex mLock;
- AudioStreamOutGeneric *mOutput;
- AudioStreamInGeneric *mInput;
- int mFd;
- bool mMicMute;
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_HARDWARE_GENERIC_H
diff --git a/services/audioflinger/AudioHardwareInterface.cpp b/services/audioflinger/AudioHardwareInterface.cpp
deleted file mode 100644
index f58e4c0..0000000
--- a/services/audioflinger/AudioHardwareInterface.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-**
-** Copyright 2007, 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 <cutils/properties.h>
-#include <string.h>
-#include <unistd.h>
-//#define LOG_NDEBUG 0
-
-#define LOG_TAG "AudioHardwareInterface"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareStub.h"
-#include "AudioHardwareGeneric.h"
-#ifdef WITH_A2DP
-#include "A2dpAudioInterface.h"
-#endif
-
-#ifdef ENABLE_AUDIO_DUMP
-#include "AudioDumpInterface.h"
-#endif
-
-
-// change to 1 to log routing calls
-#define LOG_ROUTING_CALLS 1
-
-namespace android {
-
-#if LOG_ROUTING_CALLS
-static const char* routingModeStrings[] =
-{
- "OUT OF RANGE",
- "INVALID",
- "CURRENT",
- "NORMAL",
- "RINGTONE",
- "IN_CALL",
- "IN_COMMUNICATION"
-};
-
-static const char* routeNone = "NONE";
-
-static const char* displayMode(int mode)
-{
- if ((mode < AudioSystem::MODE_INVALID) || (mode >= AudioSystem::NUM_MODES))
- return routingModeStrings[0];
- return routingModeStrings[mode+3];
-}
-#endif
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareInterface* AudioHardwareInterface::create()
-{
- /*
- * FIXME: This code needs to instantiate the correct audio device
- * interface. For now - we use compile-time switches.
- */
- AudioHardwareInterface* hw = 0;
- char value[PROPERTY_VALUE_MAX];
-
-#ifdef GENERIC_AUDIO
- hw = new AudioHardwareGeneric();
-#else
- // if running in emulation - use the emulator driver
- if (property_get("ro.kernel.qemu", value, 0)) {
- LOGD("Running in emulation - using generic audio driver");
- hw = new AudioHardwareGeneric();
- }
- else {
- LOGV("Creating Vendor Specific AudioHardware");
- hw = createAudioHardware();
- }
-#endif
- if (hw->initCheck() != NO_ERROR) {
- LOGW("Using stubbed audio hardware. No sound will be produced.");
- delete hw;
- hw = new AudioHardwareStub();
- }
-
-#ifdef WITH_A2DP
- hw = new A2dpAudioInterface(hw);
-#endif
-
-#ifdef ENABLE_AUDIO_DUMP
- // This code adds a record of buffers in a file to write calls made by AudioFlinger.
- // It replaces the current AudioHardwareInterface object by an intermediate one which
- // will record buffers in a file (after sending them to hardware) for testing purpose.
- // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
- // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
- LOGV("opening PCM dump interface");
- hw = new AudioDumpInterface(hw); // replace interface
-#endif
- return hw;
-}
-
-AudioStreamOut::~AudioStreamOut()
-{
-}
-
-AudioStreamIn::~AudioStreamIn() {}
-
-AudioHardwareBase::AudioHardwareBase()
-{
- mMode = 0;
-}
-
-status_t AudioHardwareBase::setMode(int mode)
-{
-#if LOG_ROUTING_CALLS
- LOGD("setMode(%s)", displayMode(mode));
-#endif
- if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
- return BAD_VALUE;
- if (mMode == mode)
- return ALREADY_EXISTS;
- mMode = mode;
- return NO_ERROR;
-}
-
-// default implementation
-status_t AudioHardwareBase::setParameters(const String8& keyValuePairs)
-{
- return NO_ERROR;
-}
-
-// default implementation
-String8 AudioHardwareBase::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-// default implementation
-size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- if (sampleRate != 8000) {
- LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
- return 0;
- }
- if (format != AudioSystem::PCM_16_BIT) {
- LOGW("getInputBufferSize bad format: %d", format);
- return 0;
- }
- if (channelCount != 1) {
- LOGW("getInputBufferSize bad channel count: %d", channelCount);
- return 0;
- }
-
- return 320;
-}
-
-status_t AudioHardwareBase::dumpState(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioHardwareBase::dumpState\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmMode: %d\n", mMode);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- dump(fd, args); // Dump the state of the concrete child.
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/audioflinger/AudioHardwareStub.cpp b/services/audioflinger/AudioHardwareStub.cpp
deleted file mode 100644
index d481150..0000000
--- a/services/audioflinger/AudioHardwareStub.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/* //device/servers/AudioFlinger/AudioHardwareStub.cpp
-**
-** Copyright 2007, 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 <stdint.h>
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareStub.h"
-#include <media/AudioRecord.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareStub::AudioHardwareStub() : mMicMute(false)
-{
-}
-
-AudioHardwareStub::~AudioHardwareStub()
-{
-}
-
-status_t AudioHardwareStub::initCheck()
-{
- return NO_ERROR;
-}
-
-AudioStreamOut* AudioHardwareStub::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AudioStreamOutStub* out = new AudioStreamOutStub();
- status_t lStatus = out->set(format, channels, sampleRate);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR)
- return out;
- delete out;
- return 0;
-}
-
-void AudioHardwareStub::closeOutputStream(AudioStreamOut* out)
-{
- delete out;
-}
-
-AudioStreamIn* AudioHardwareStub::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
- status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- // check for valid input source
- if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
- return 0;
- }
-
- AudioStreamInStub* in = new AudioStreamInStub();
- status_t lStatus = in->set(format, channels, sampleRate, acoustics);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR)
- return in;
- delete in;
- return 0;
-}
-
-void AudioHardwareStub::closeInputStream(AudioStreamIn* in)
-{
- delete in;
-}
-
-status_t AudioHardwareStub::setVoiceVolume(float volume)
-{
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::setMasterVolume(float volume)
-{
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- result.append("AudioHardwareStub::dumpInternals\n");
- snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args)
-{
- dumpInternals(fd, args);
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamOutStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate)
-{
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
-
- return NO_ERROR;
-}
-
-ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes)
-{
- // fake timing for audio output
- usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
- return bytes;
-}
-
-status_t AudioStreamOutStub::standby()
-{
- return NO_ERROR;
-}
-
-status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n");
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-String8 AudioStreamOutStub::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames)
-{
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics)
-{
- return NO_ERROR;
-}
-
-ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes)
-{
- // fake timing for audio input
- usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
- memset(buffer, 0, bytes);
- return bytes;
-}
-
-status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamInStub::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-String8 AudioStreamInStub::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/audioflinger/AudioHardwareStub.h b/services/audioflinger/AudioHardwareStub.h
deleted file mode 100644
index 06a29de..0000000
--- a/services/audioflinger/AudioHardwareStub.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* //device/servers/AudioFlinger/AudioHardwareStub.h
-**
-** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_STUB_H
-#define ANDROID_AUDIO_HARDWARE_STUB_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class AudioStreamOutStub : public AudioStreamOut {
-public:
- virtual status_t set(int *pFormat, uint32_t *pChannels, uint32_t *pRate);
- virtual uint32_t sampleRate() const { return 44100; }
- virtual size_t bufferSize() const { return 4096; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return 0; }
- virtual status_t setVolume(float left, float right) { return NO_ERROR; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-};
-
-class AudioStreamInStub : public AudioStreamIn {
-public:
- virtual status_t set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics);
- virtual uint32_t sampleRate() const { return 8000; }
- virtual size_t bufferSize() const { return 320; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_IN_MONO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual status_t setGain(float gain) { return NO_ERROR; }
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t standby() { return NO_ERROR; }
- virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const { return 0; }
-};
-
-class AudioHardwareStub : public AudioHardwareBase
-{
-public:
- AudioHardwareStub();
- virtual ~AudioHardwareStub();
- virtual status_t initCheck();
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- // mic mute
- virtual status_t setMicMute(bool state) { mMicMute = state; return NO_ERROR; }
- virtual status_t getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; }
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- bool mMicMute;
-private:
- status_t dumpInternals(int fd, const Vector<String16>& args);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_HARDWARE_STUB_H
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
deleted file mode 100644
index f5e7343..0000000
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ /dev/null
@@ -1,2286 +0,0 @@
-/*
- * Copyright (C) 2009 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_TAG "AudioPolicyManagerBase"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <hardware_legacy/AudioPolicyManagerBase.h>
-#include <media/mediarecorder.h>
-#include <math.h>
-
-namespace android {
-
-
-// ----------------------------------------------------------------------------
-// AudioPolicyInterface implementation
-// ----------------------------------------------------------------------------
-
-
-status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address)
-{
-
- LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
-
- // connect/disconnect only 1 device at a time
- if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
-
- if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
- LOGE("setDeviceConnectionState() invalid address: %s", device_address);
- return BAD_VALUE;
- }
-
- // handle output devices
- if (AudioSystem::isOutputDevice(device)) {
-
-#ifndef WITH_A2DP
- if (AudioSystem::isA2dpDevice(device)) {
- LOGE("setDeviceConnectionState() invalid device: %x", device);
- return BAD_VALUE;
- }
-#endif
-
- switch (state)
- {
- // handle output device connection
- case AudioSystem::DEVICE_STATE_AVAILABLE:
- if (mAvailableOutputDevices & device) {
- LOGW("setDeviceConnectionState() device already connected: %x", device);
- return INVALID_OPERATION;
- }
- LOGV("setDeviceConnectionState() connecting device %x", device);
-
- // register new device as available
- mAvailableOutputDevices |= device;
-
-#ifdef WITH_A2DP
- // handle A2DP device connection
- if (AudioSystem::isA2dpDevice(device)) {
- status_t status = handleA2dpConnection(device, device_address);
- if (status != NO_ERROR) {
- mAvailableOutputDevices &= ~device;
- return status;
- }
- } else
-#endif
- {
- if (AudioSystem::isBluetoothScoDevice(device)) {
- LOGV("setDeviceConnectionState() BT SCO device, address %s", device_address);
- // keep track of SCO device address
- mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
- }
- }
- break;
- // handle output device disconnection
- case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableOutputDevices & device)) {
- LOGW("setDeviceConnectionState() device not connected: %x", device);
- return INVALID_OPERATION;
- }
-
-
- LOGV("setDeviceConnectionState() disconnecting device %x", device);
- // remove device from available output devices
- mAvailableOutputDevices &= ~device;
-
-#ifdef WITH_A2DP
- // handle A2DP device disconnection
- if (AudioSystem::isA2dpDevice(device)) {
- status_t status = handleA2dpDisconnection(device, device_address);
- if (status != NO_ERROR) {
- mAvailableOutputDevices |= device;
- return status;
- }
- } else
-#endif
- {
- if (AudioSystem::isBluetoothScoDevice(device)) {
- mScoDeviceAddress = "";
- }
- }
- } break;
-
- default:
- LOGE("setDeviceConnectionState() invalid state: %x", state);
- return BAD_VALUE;
- }
-
- // request routing change if necessary
- uint32_t newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkA2dpSuspend();
- checkOutputForAllStrategies();
- // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
- if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
- closeA2dpOutputs();
- }
-#endif
- updateDeviceForStrategy();
- setOutputDevice(mHardwareOutput, newDevice);
-
- if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
- } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else {
- return NO_ERROR;
- }
- }
- // handle input devices
- if (AudioSystem::isInputDevice(device)) {
-
- switch (state)
- {
- // handle input device connection
- case AudioSystem::DEVICE_STATE_AVAILABLE: {
- if (mAvailableInputDevices & device) {
- LOGW("setDeviceConnectionState() device already connected: %d", device);
- return INVALID_OPERATION;
- }
- mAvailableInputDevices |= device;
- }
- break;
-
- // handle input device disconnection
- case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableInputDevices & device)) {
- LOGW("setDeviceConnectionState() device not connected: %d", device);
- return INVALID_OPERATION;
- }
- mAvailableInputDevices &= ~device;
- } break;
-
- default:
- LOGE("setDeviceConnectionState() invalid state: %x", state);
- return BAD_VALUE;
- }
-
- audio_io_handle_t activeInput = getActiveInput();
- if (activeInput != 0) {
- AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
- uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
- if (newDevice != inputDesc->mDevice) {
- LOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
- inputDesc->mDevice, newDevice, activeInput);
- inputDesc->mDevice = newDevice;
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
- mpClientInterface->setParameters(activeInput, param.toString());
- }
- }
-
- return NO_ERROR;
- }
-
- LOGW("setDeviceConnectionState() invalid device: %x", device);
- return BAD_VALUE;
-}
-
-AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(AudioSystem::audio_devices device,
- const char *device_address)
-{
- AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
- String8 address = String8(device_address);
- if (AudioSystem::isOutputDevice(device)) {
- if (device & mAvailableOutputDevices) {
-#ifdef WITH_A2DP
- if (AudioSystem::isA2dpDevice(device) &&
- address != "" && mA2dpDeviceAddress != address) {
- return state;
- }
-#endif
- if (AudioSystem::isBluetoothScoDevice(device) &&
- address != "" && mScoDeviceAddress != address) {
- return state;
- }
- state = AudioSystem::DEVICE_STATE_AVAILABLE;
- }
- } else if (AudioSystem::isInputDevice(device)) {
- if (device & mAvailableInputDevices) {
- state = AudioSystem::DEVICE_STATE_AVAILABLE;
- }
- }
-
- return state;
-}
-
-void AudioPolicyManagerBase::setPhoneState(int state)
-{
- LOGV("setPhoneState() state %d", state);
- uint32_t newDevice = 0;
- if (state < 0 || state >= AudioSystem::NUM_MODES) {
- LOGW("setPhoneState() invalid state %d", state);
- return;
- }
-
- if (state == mPhoneState ) {
- LOGW("setPhoneState() setting same state %d", state);
- return;
- }
-
- // if leaving call state, handle special case of active streams
- // pertaining to sonification strategy see handleIncallSonification()
- if (isInCall()) {
- LOGV("setPhoneState() in call state management: new state is %d", state);
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- handleIncallSonification(stream, false, true);
- }
- }
-
- // store previous phone state for management of sonification strategy below
- int oldState = mPhoneState;
- mPhoneState = state;
- bool force = false;
-
- // are we entering or starting a call
- if (!isStateInCall(oldState) && isStateInCall(state)) {
- LOGV(" Entering call in setPhoneState()");
- // force routing command to audio hardware when starting a call
- // even if no device change is needed
- force = true;
- } else if (isStateInCall(oldState) && !isStateInCall(state)) {
- LOGV(" Exiting call in setPhoneState()");
- // force routing command to audio hardware when exiting a call
- // even if no device change is needed
- force = true;
- } else if (isStateInCall(state) && (state != oldState)) {
- LOGV(" Switching between telephony and VoIP in setPhoneState()");
- // force routing command to audio hardware when switching between telephony and VoIP
- // even if no device change is needed
- force = true;
- }
-
- // check for device and output changes triggered by new phone state
- newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkA2dpSuspend();
- checkOutputForAllStrategies();
-#endif
- updateDeviceForStrategy();
-
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
-
- // force routing command to audio hardware when ending call
- // even if no device change is needed
- if (isStateInCall(oldState) && newDevice == 0) {
- newDevice = hwOutputDesc->device();
- }
-
- // when changing from ring tone to in call mode, mute the ringing tone
- // immediately and delay the route change to avoid sending the ring tone
- // tail into the earpiece or headset.
- int delayMs = 0;
- if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) {
- // delay the device change command by twice the output latency to have some margin
- // and be sure that audio buffers not yet affected by the mute are out when
- // we actually apply the route change
- delayMs = hwOutputDesc->mLatency*2;
- setStreamMute(AudioSystem::RING, true, mHardwareOutput);
- }
-
- // change routing is necessary
- setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
-
- // if entering in call state, handle special case of active streams
- // pertaining to sonification strategy see handleIncallSonification()
- if (isStateInCall(state)) {
- LOGV("setPhoneState() in call state management: new state is %d", state);
- // unmute the ringing tone after a sufficient delay if it was muted before
- // setting output device above
- if (oldState == AudioSystem::MODE_RINGTONE) {
- setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
- }
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- handleIncallSonification(stream, true, true);
- }
- }
-
- // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
- if (state == AudioSystem::MODE_RINGTONE &&
- isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
- mLimitRingtoneVolume = true;
- } else {
- mLimitRingtoneVolume = false;
- }
-}
-
-void AudioPolicyManagerBase::setRingerMode(uint32_t mode, uint32_t mask)
-{
- LOGV("setRingerMode() mode %x, mask %x", mode, mask);
-
- mRingerMode = mode;
-}
-
-void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
-{
- LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
-
- bool forceVolumeReeval = false;
- switch(usage) {
- case AudioSystem::FOR_COMMUNICATION:
- if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
- config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
- return;
- }
- forceVolumeReeval = true;
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_MEDIA:
- if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_ANALOG_DOCK &&
- config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_RECORD:
- if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_RECORD", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_DOCK:
- if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
- config != AudioSystem::FORCE_BT_DESK_DOCK &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_ANALOG_DOCK &&
- config != AudioSystem::FORCE_DIGITAL_DOCK) {
- LOGW("setForceUse() invalid config %d for FOR_DOCK", config);
- }
- forceVolumeReeval = true;
- mForceUse[usage] = config;
- break;
- default:
- LOGW("setForceUse() invalid usage %d", usage);
- break;
- }
-
- // check for device and output changes triggered by new phone state
- uint32_t newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkA2dpSuspend();
- checkOutputForAllStrategies();
-#endif
- updateDeviceForStrategy();
- setOutputDevice(mHardwareOutput, newDevice);
- if (forceVolumeReeval) {
- applyStreamVolumes(mHardwareOutput, newDevice, 0, true);
- }
-
- audio_io_handle_t activeInput = getActiveInput();
- if (activeInput != 0) {
- AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
- newDevice = getDeviceForInputSource(inputDesc->mInputSource);
- if (newDevice != inputDesc->mDevice) {
- LOGV("setForceUse() changing device from %x to %x for input %d",
- inputDesc->mDevice, newDevice, activeInput);
- inputDesc->mDevice = newDevice;
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
- mpClientInterface->setParameters(activeInput, param.toString());
- }
- }
-
-}
-
-AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
-{
- return mForceUse[usage];
-}
-
-void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value)
-{
- LOGV("setSystemProperty() property %s, value %s", property, value);
- if (strcmp(property, "ro.camera.sound.forced") == 0) {
- if (atoi(value)) {
- LOGV("ENFORCED_AUDIBLE cannot be muted");
- mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
- } else {
- LOGV("ENFORCED_AUDIBLE can be muted");
- mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
- }
- }
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::output_flags flags)
-{
- audio_io_handle_t output = 0;
- uint32_t latency = 0;
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
- uint32_t device = getDeviceForStrategy(strategy);
- LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
-
-#ifdef AUDIO_POLICY_TEST
- if (mCurOutput != 0) {
- LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
- mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
-
- if (mTestOutputs[mCurOutput] == 0) {
- LOGV("getOutput() opening test output");
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = mTestDevice;
- outputDesc->mSamplingRate = mTestSamplingRate;
- outputDesc->mFormat = mTestFormat;
- outputDesc->mChannels = mTestChannels;
- outputDesc->mLatency = mTestLatencyMs;
- outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
- outputDesc->mRefCount[stream] = 0;
- mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mTestOutputs[mCurOutput]) {
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"),mCurOutput);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
- addOutput(mTestOutputs[mCurOutput], outputDesc);
- }
- }
- return mTestOutputs[mCurOutput];
- }
-#endif //AUDIO_POLICY_TEST
-
- // open a direct output if required by specified parameters
- if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
-
- LOGV("getOutput() opening direct output device %x", device);
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = device;
- outputDesc->mSamplingRate = samplingRate;
- outputDesc->mFormat = format;
- outputDesc->mChannels = channels;
- outputDesc->mLatency = 0;
- outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
- outputDesc->mRefCount[stream] = 0;
- outputDesc->mStopTime[stream] = 0;
- output = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
-
- // only accept an output with the requeted parameters
- if (output == 0 ||
- (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
- (format != 0 && format != outputDesc->mFormat) ||
- (channels != 0 && channels != outputDesc->mChannels)) {
- LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d",
- samplingRate, format, channels);
- if (output != 0) {
- mpClientInterface->closeOutput(output);
- }
- delete outputDesc;
- return 0;
- }
- addOutput(output, outputDesc);
- return output;
- }
-
- if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO &&
- channels != AudioSystem::CHANNEL_OUT_STEREO) {
- return 0;
- }
- // open a non direct output
-
- // get which output is suitable for the specified stream. The actual routing change will happen
- // when startOutput() will be called
- uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP;
- if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) {
-#ifdef WITH_A2DP
- if (a2dpUsedForSonification() && a2dpDevice != 0) {
- // if playing on 2 devices among which one is A2DP, use duplicated output
- LOGV("getOutput() using duplicated output");
- LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device);
- output = mDuplicatedOutput;
- } else
-#endif
- {
- // if playing on 2 devices among which none is A2DP, use hardware output
- output = mHardwareOutput;
- }
- LOGV("getOutput() using output %d for 2 devices %x", output, device);
- } else {
-#ifdef WITH_A2DP
- if (a2dpDevice != 0) {
- // if playing on A2DP device, use a2dp output
- LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device);
- output = mA2dpOutput;
- } else
-#endif
- {
- // if playing on not A2DP device, use hardware output
- output = mHardwareOutput;
- }
- }
-
-
- LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x",
- stream, samplingRate, format, channels, flags);
-
- return output;
-}
-
-status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session)
-{
- LOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("startOutput() unknow output %d", output);
- return BAD_VALUE;
- }
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
-
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
- setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
- }
-#endif
-
- // incremenent usage count for this stream on the requested output:
- // NOTE that the usage count is the same for duplicated output and hardware output which is
- // necassary for a correct control of hardware output routing by startOutput() and stopOutput()
- outputDesc->changeRefCount(stream, 1);
-
- setOutputDevice(output, getNewDevice(output));
-
- // handle special case for sonification while in call
- if (isInCall()) {
- handleIncallSonification(stream, true, false);
- }
-
- // apply volume rules for current stream and device if necessary
- checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
- int session)
-{
- LOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("stopOutput() unknow output %d", output);
- return BAD_VALUE;
- }
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
-
- // handle special case for sonification while in call
- if (isInCall()) {
- handleIncallSonification(stream, false, false);
- }
-
- if (outputDesc->mRefCount[stream] > 0) {
- // decrement usage count of this stream on the output
- outputDesc->changeRefCount(stream, -1);
- // store time at which the stream was stopped - see isStreamActive()
- outputDesc->mStopTime[stream] = systemTime();
-
- setOutputDevice(output, getNewDevice(output), false, outputDesc->mLatency*2);
-
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
- strategy == STRATEGY_SONIFICATION) {
- setStrategyMute(STRATEGY_MEDIA,
- false,
- mA2dpOutput,
- mOutputs.valueFor(mHardwareOutput)->mLatency*2);
- }
-#endif
- if (output != mHardwareOutput) {
- setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
- }
- return NO_ERROR;
- } else {
- LOGW("stopOutput() refcount is already 0 for output %d", output);
- return INVALID_OPERATION;
- }
-}
-
-void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
-{
- LOGV("releaseOutput() %d", output);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("releaseOutput() releasing unknown output %d", output);
- return;
- }
-
-#ifdef AUDIO_POLICY_TEST
- int testIndex = testOutputIndex(output);
- if (testIndex != 0) {
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- if (outputDesc->refCount() == 0) {
- mpClientInterface->closeOutput(output);
- delete mOutputs.valueAt(index);
- mOutputs.removeItem(output);
- mTestOutputs[testIndex] = 0;
- }
- return;
- }
-#endif //AUDIO_POLICY_TEST
-
- if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
- mpClientInterface->closeOutput(output);
- delete mOutputs.valueAt(index);
- mOutputs.removeItem(output);
- }
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::audio_in_acoustics acoustics)
-{
- audio_io_handle_t input = 0;
- uint32_t device = getDeviceForInputSource(inputSource);
-
- LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
-
- if (device == 0) {
- return 0;
- }
-
- // adapt channel selection to input source
- switch(inputSource) {
- case AUDIO_SOURCE_VOICE_UPLINK:
- channels = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
- break;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- channels = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
- break;
- case AUDIO_SOURCE_VOICE_CALL:
- channels = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
- break;
- default:
- break;
- }
-
- AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
-
- inputDesc->mInputSource = inputSource;
- inputDesc->mDevice = device;
- inputDesc->mSamplingRate = samplingRate;
- inputDesc->mFormat = format;
- inputDesc->mChannels = channels;
- inputDesc->mAcoustics = acoustics;
- inputDesc->mRefCount = 0;
- input = mpClientInterface->openInput(&inputDesc->mDevice,
- &inputDesc->mSamplingRate,
- &inputDesc->mFormat,
- &inputDesc->mChannels,
- inputDesc->mAcoustics);
-
- // only accept input with the exact requested set of parameters
- if (input == 0 ||
- (samplingRate != inputDesc->mSamplingRate) ||
- (format != inputDesc->mFormat) ||
- (channels != inputDesc->mChannels)) {
- LOGV("getInput() failed opening input: samplingRate %d, format %d, channels %d",
- samplingRate, format, channels);
- if (input != 0) {
- mpClientInterface->closeInput(input);
- }
- delete inputDesc;
- return 0;
- }
- mInputs.add(input, inputDesc);
- return input;
-}
-
-status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
-{
- LOGV("startInput() input %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("startInput() unknow input %d", input);
- return BAD_VALUE;
- }
- AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
-
-#ifdef AUDIO_POLICY_TEST
- if (mTestInput == 0)
-#endif //AUDIO_POLICY_TEST
- {
- // refuse 2 active AudioRecord clients at the same time
- if (getActiveInput() != 0) {
- LOGW("startInput() input %d failed: other input already started", input);
- return INVALID_OPERATION;
- }
- }
-
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
-
- param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
- LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
-
- mpClientInterface->setParameters(input, param.toString());
-
- inputDesc->mRefCount = 1;
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
-{
- LOGV("stopInput() input %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("stopInput() unknow input %d", input);
- return BAD_VALUE;
- }
- AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
-
- if (inputDesc->mRefCount == 0) {
- LOGW("stopInput() input %d already stopped", input);
- return INVALID_OPERATION;
- } else {
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), 0);
- mpClientInterface->setParameters(input, param.toString());
- inputDesc->mRefCount = 0;
- return NO_ERROR;
- }
-}
-
-void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
-{
- LOGV("releaseInput() %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("releaseInput() releasing unknown input %d", input);
- return;
- }
- mpClientInterface->closeInput(input);
- delete mInputs.valueAt(index);
- mInputs.removeItem(input);
- LOGV("releaseInput() exit");
-}
-
-void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
- int indexMin,
- int indexMax)
-{
- LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
- if (indexMin < 0 || indexMin >= indexMax) {
- LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
- return;
- }
- mStreams[stream].mIndexMin = indexMin;
- mStreams[stream].mIndexMax = indexMax;
-}
-
-status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
-{
-
- if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
- return BAD_VALUE;
- }
-
- // Force max volume if stream cannot be muted
- if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
-
- LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
- mStreams[stream].mIndexCur = index;
-
- // compute and apply stream volume on all outputs according to connected device
- status_t status = NO_ERROR;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
- if (volStatus != NO_ERROR) {
- status = volStatus;
- }
- }
- return status;
-}
-
-status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
-{
- if (index == 0) {
- return BAD_VALUE;
- }
- LOGV("getStreamVolumeIndex() stream %d", stream);
- *index = mStreams[stream].mIndexCur;
- return NO_ERROR;
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc)
-{
- LOGV("getOutputForEffect()");
- // apply simple rule where global effects are attached to the same output as MUSIC streams
- return getOutput(AudioSystem::MUSIC);
-}
-
-status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,
- audio_io_handle_t output,
- uint32_t strategy,
- int session,
- int id)
-{
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("registerEffect() unknown output %d", output);
- return INVALID_OPERATION;
- }
-
- if (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {
- LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
- desc->name, (float)desc->cpuLoad/10);
- return INVALID_OPERATION;
- }
- if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
- LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
- desc->name, desc->memoryUsage);
- return INVALID_OPERATION;
- }
- mTotalEffectsCpuLoad += desc->cpuLoad;
- mTotalEffectsMemory += desc->memoryUsage;
- LOGV("registerEffect() effect %s, output %d, strategy %d session %d id %d",
- desc->name, output, strategy, session, id);
-
- LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
-
- EffectDescriptor *pDesc = new EffectDescriptor();
- memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
- pDesc->mOutput = output;
- pDesc->mStrategy = (routing_strategy)strategy;
- pDesc->mSession = session;
- mEffects.add(id, pDesc);
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::unregisterEffect(int id)
-{
- ssize_t index = mEffects.indexOfKey(id);
- if (index < 0) {
- LOGW("unregisterEffect() unknown effect ID %d", id);
- return INVALID_OPERATION;
- }
-
- EffectDescriptor *pDesc = mEffects.valueAt(index);
-
- if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
- LOGW("unregisterEffect() CPU load %d too high for total %d",
- pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
- pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
- }
- mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
- if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
- LOGW("unregisterEffect() memory %d too big for total %d",
- pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
- pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
- }
- mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
- LOGV("unregisterEffect() effect %s, ID %d, CPU %d, memory %d",
- pDesc->mDesc.name, id, pDesc->mDesc.cpuLoad, pDesc->mDesc.memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
-
- mEffects.removeItem(id);
- delete pDesc;
-
- return NO_ERROR;
-}
-
-bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const
-{
- nsecs_t sysTime = systemTime();
- for (size_t i = 0; i < mOutputs.size(); i++) {
- if (mOutputs.valueAt(i)->mRefCount[stream] != 0 ||
- ns2ms(sysTime - mOutputs.valueAt(i)->mStopTime[stream]) < inPastMs) {
- return true;
- }
- }
- return false;
-}
-
-
-status_t AudioPolicyManagerBase::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
- result.append(buffer);
- snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
- result.append(buffer);
-#ifdef WITH_A2DP
- snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput);
- result.append(buffer);
- snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput);
- result.append(buffer);
- snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
- result.append(buffer);
-#endif
- snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
- result.append(buffer);
- snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
- result.append(buffer);
- snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
- result.append(buffer);
- snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
- result.append(buffer);
- snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- snprintf(buffer, SIZE, "\nOutputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mOutputs.size(); i++) {
- snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mOutputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nInputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mInputs.size(); i++) {
- snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mInputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nStreams dump:\n");
- write(fd, buffer, strlen(buffer));
- snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Can be muted\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- snprintf(buffer, SIZE, " %02d", i);
- mStreams[i].dump(buffer + 3, SIZE);
- write(fd, buffer, strlen(buffer));
- }
-
- snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
- (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
- write(fd, buffer, strlen(buffer));
-
- snprintf(buffer, SIZE, "Registered effects:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mEffects.size(); i++) {
- snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mEffects.valueAt(i)->dump(fd);
- }
-
-
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-// AudioPolicyManagerBase
-// ----------------------------------------------------------------------------
-
-AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
- :
-#ifdef AUDIO_POLICY_TEST
- Thread(false),
-#endif //AUDIO_POLICY_TEST
- mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),
- mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
- mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
- mA2dpSuspended(false)
-{
- mpClientInterface = clientInterface;
-
- for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
- mForceUse[i] = AudioSystem::FORCE_NONE;
- }
-
- initializeVolumeCurves();
-
- // devices available by default are speaker, ear piece and microphone
- mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
- AudioSystem::DEVICE_OUT_SPEAKER;
- mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
-
-#ifdef WITH_A2DP
- mA2dpOutput = 0;
- mDuplicatedOutput = 0;
- mA2dpDeviceAddress = String8("");
-#endif
- mScoDeviceAddress = String8("");
-
- // open hardware output
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
-
- if (mHardwareOutput == 0) {
- LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
- outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
- } else {
- addOutput(mHardwareOutput, outputDesc);
- setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
- //TODO: configure audio effect output stage here
- }
-
- updateDeviceForStrategy();
-#ifdef AUDIO_POLICY_TEST
- if (mHardwareOutput != 0) {
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
-
- mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
- mTestSamplingRate = 44100;
- mTestFormat = AudioSystem::PCM_16_BIT;
- mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
- mTestLatencyMs = 0;
- mCurOutput = 0;
- mDirectOutput = false;
- for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
- mTestOutputs[i] = 0;
- }
-
- const size_t SIZE = 256;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "AudioPolicyManagerTest");
- run(buffer, ANDROID_PRIORITY_AUDIO);
- }
-#endif //AUDIO_POLICY_TEST
-}
-
-AudioPolicyManagerBase::~AudioPolicyManagerBase()
-{
-#ifdef AUDIO_POLICY_TEST
- exit();
-#endif //AUDIO_POLICY_TEST
- for (size_t i = 0; i < mOutputs.size(); i++) {
- mpClientInterface->closeOutput(mOutputs.keyAt(i));
- delete mOutputs.valueAt(i);
- }
- mOutputs.clear();
- for (size_t i = 0; i < mInputs.size(); i++) {
- mpClientInterface->closeInput(mInputs.keyAt(i));
- delete mInputs.valueAt(i);
- }
- mInputs.clear();
-}
-
-status_t AudioPolicyManagerBase::initCheck()
-{
- return (mHardwareOutput == 0) ? NO_INIT : NO_ERROR;
-}
-
-#ifdef AUDIO_POLICY_TEST
-bool AudioPolicyManagerBase::threadLoop()
-{
- LOGV("entering threadLoop()");
- while (!exitPending())
- {
- String8 command;
- int valueInt;
- String8 value;
-
- Mutex::Autolock _l(mLock);
- mWaitWorkCV.waitRelative(mLock, milliseconds(50));
-
- command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
- AudioParameter param = AudioParameter(command);
-
- if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
- valueInt != 0) {
- LOGV("Test command %s received", command.string());
- String8 target;
- if (param.get(String8("target"), target) != NO_ERROR) {
- target = "Manager";
- }
- if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_output"));
- mCurOutput = valueInt;
- }
- if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_direct"));
- if (value == "false") {
- mDirectOutput = false;
- } else if (value == "true") {
- mDirectOutput = true;
- }
- }
- if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_input"));
- mTestInput = valueInt;
- }
-
- if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_format"));
- int format = AudioSystem::INVALID_FORMAT;
- if (value == "PCM 16 bits") {
- format = AudioSystem::PCM_16_BIT;
- } else if (value == "PCM 8 bits") {
- format = AudioSystem::PCM_8_BIT;
- } else if (value == "Compressed MP3") {
- format = AudioSystem::MP3;
- }
- if (format != AudioSystem::INVALID_FORMAT) {
- if (target == "Manager") {
- mTestFormat = format;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("format"), format);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
- if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_channels"));
- int channels = 0;
-
- if (value == "Channels Stereo") {
- channels = AudioSystem::CHANNEL_OUT_STEREO;
- } else if (value == "Channels Mono") {
- channels = AudioSystem::CHANNEL_OUT_MONO;
- }
- if (channels != 0) {
- if (target == "Manager") {
- mTestChannels = channels;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("channels"), channels);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
- if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_sampleRate"));
- if (valueInt >= 0 && valueInt <= 96000) {
- int samplingRate = valueInt;
- if (target == "Manager") {
- mTestSamplingRate = samplingRate;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("sampling_rate"), samplingRate);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
-
- if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_reopen"));
-
- mpClientInterface->closeOutput(mHardwareOutput);
- delete mOutputs.valueFor(mHardwareOutput);
- mOutputs.removeItem(mHardwareOutput);
-
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mHardwareOutput == 0) {
- LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
- outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
- } else {
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
- addOutput(mHardwareOutput, outputDesc);
- }
- }
-
-
- mpClientInterface->setParameters(0, String8("test_cmd_policy="));
- }
- }
- return false;
-}
-
-void AudioPolicyManagerBase::exit()
-{
- {
- AutoMutex _l(mLock);
- requestExit();
- mWaitWorkCV.signal();
- }
- requestExitAndWait();
-}
-
-int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output)
-{
- for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
- if (output == mTestOutputs[i]) return i;
- }
- return 0;
-}
-#endif //AUDIO_POLICY_TEST
-
-// ---
-
-void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc)
-{
- outputDesc->mId = id;
- mOutputs.add(id, outputDesc);
-}
-
-
-#ifdef WITH_A2DP
-status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,
- const char *device_address)
-{
- // when an A2DP device is connected, open an A2DP and a duplicated output
- LOGV("opening A2DP output for device %s", device_address);
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = device;
- mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mA2dpOutput) {
- // add A2DP output descriptor
- addOutput(mA2dpOutput, outputDesc);
-
- //TODO: configure audio effect output stage here
-
- // set initial stream volume for A2DP device
- applyStreamVolumes(mA2dpOutput, device);
- if (a2dpUsedForSonification()) {
- mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
- }
- if (mDuplicatedOutput != 0 ||
- !a2dpUsedForSonification()) {
- // If both A2DP and duplicated outputs are open, send device address to A2DP hardware
- // interface
- AudioParameter param;
- param.add(String8("a2dp_sink_address"), String8(device_address));
- mpClientInterface->setParameters(mA2dpOutput, param.toString());
- mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
-
- if (a2dpUsedForSonification()) {
- // add duplicated output descriptor
- AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();
- dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);
- dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);
- dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;
- dupOutputDesc->mFormat = outputDesc->mFormat;
- dupOutputDesc->mChannels = outputDesc->mChannels;
- dupOutputDesc->mLatency = outputDesc->mLatency;
- addOutput(mDuplicatedOutput, dupOutputDesc);
- applyStreamVolumes(mDuplicatedOutput, device);
- }
- } else {
- LOGW("getOutput() could not open duplicated output for %d and %d",
- mHardwareOutput, mA2dpOutput);
- mpClientInterface->closeOutput(mA2dpOutput);
- mOutputs.removeItem(mA2dpOutput);
- mA2dpOutput = 0;
- delete outputDesc;
- return NO_INIT;
- }
- } else {
- LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device);
- delete outputDesc;
- return NO_INIT;
- }
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
-
- if (!a2dpUsedForSonification()) {
- // mute music on A2DP output if a notification or ringtone is playing
- uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
- for (uint32_t i = 0; i < refCount; i++) {
- setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
- }
- }
-
- mA2dpSuspended = false;
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device,
- const char *device_address)
-{
- if (mA2dpOutput == 0) {
- LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!");
- return INVALID_OPERATION;
- }
-
- if (mA2dpDeviceAddress != device_address) {
- LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address);
- return INVALID_OPERATION;
- }
-
- // mute media strategy to avoid outputting sound on hardware output while music stream
- // is switched from A2DP output and before music is paused by music application
- setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
- setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
-
- if (!a2dpUsedForSonification()) {
- // unmute music on A2DP output if a notification or ringtone is playing
- uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
- for (uint32_t i = 0; i < refCount; i++) {
- setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
- }
- }
- mA2dpDeviceAddress = "";
- mA2dpSuspended = false;
- return NO_ERROR;
-}
-
-void AudioPolicyManagerBase::closeA2dpOutputs()
-{
-
- LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
-
- if (mDuplicatedOutput != 0) {
- AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
- // As all active tracks on duplicated output will be deleted,
- // and as they were also referenced on hardware output, the reference
- // count for their stream type must be adjusted accordingly on
- // hardware output.
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- int refCount = dupOutputDesc->mRefCount[i];
- hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
- }
-
- mpClientInterface->closeOutput(mDuplicatedOutput);
- delete mOutputs.valueFor(mDuplicatedOutput);
- mOutputs.removeItem(mDuplicatedOutput);
- mDuplicatedOutput = 0;
- }
- if (mA2dpOutput != 0) {
- AudioParameter param;
- param.add(String8("closing"), String8("true"));
- mpClientInterface->setParameters(mA2dpOutput, param.toString());
-
- mpClientInterface->closeOutput(mA2dpOutput);
- delete mOutputs.valueFor(mA2dpOutput);
- mOutputs.removeItem(mA2dpOutput);
- mA2dpOutput = 0;
- }
-}
-
-void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy)
-{
- uint32_t prevDevice = getDeviceForStrategy(strategy);
- uint32_t curDevice = getDeviceForStrategy(strategy, false);
- bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
- bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
- audio_io_handle_t srcOutput = 0;
- audio_io_handle_t dstOutput = 0;
-
- if (a2dpWasUsed && !a2dpIsUsed) {
- bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2);
- dstOutput = mHardwareOutput;
- if (dupUsed) {
- LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy);
- srcOutput = mDuplicatedOutput;
- } else {
- LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
- srcOutput = mA2dpOutput;
- }
- }
- if (a2dpIsUsed && !a2dpWasUsed) {
- bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
- srcOutput = mHardwareOutput;
- if (dupUsed) {
- LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy);
- dstOutput = mDuplicatedOutput;
- } else {
- LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy);
- dstOutput = mA2dpOutput;
- }
- }
-
- if (srcOutput != 0 && dstOutput != 0) {
- // Move effects associated to this strategy from previous output to new output
- for (size_t i = 0; i < mEffects.size(); i++) {
- EffectDescriptor *desc = mEffects.valueAt(i);
- if (desc->mSession != AudioSystem::SESSION_OUTPUT_STAGE &&
- desc->mStrategy == strategy &&
- desc->mOutput == srcOutput) {
- LOGV("checkOutputForStrategy() moving effect %d to output %d", mEffects.keyAt(i), dstOutput);
- mpClientInterface->moveEffects(desc->mSession, srcOutput, dstOutput);
- desc->mOutput = dstOutput;
- }
- }
- // Move tracks associated to this strategy from previous output to new output
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- if (getStrategy((AudioSystem::stream_type)i) == strategy) {
- mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, dstOutput);
- }
- }
- }
-}
-
-void AudioPolicyManagerBase::checkOutputForAllStrategies()
-{
- checkOutputForStrategy(STRATEGY_PHONE);
- checkOutputForStrategy(STRATEGY_SONIFICATION);
- checkOutputForStrategy(STRATEGY_MEDIA);
- checkOutputForStrategy(STRATEGY_DTMF);
-}
-
-void AudioPolicyManagerBase::checkA2dpSuspend()
-{
- // suspend A2DP output if:
- // (NOT already suspended) &&
- // ((SCO device is connected &&
- // (forced usage for communication || for record is SCO))) ||
- // (phone state is ringing || in call)
- //
- // restore A2DP output if:
- // (Already suspended) &&
- // ((SCO device is NOT connected ||
- // (forced usage NOT for communication && NOT for record is SCO))) &&
- // (phone state is NOT ringing && NOT in call)
- //
- if (mA2dpOutput == 0) {
- return;
- }
-
- if (mA2dpSuspended) {
- if (((mScoDeviceAddress == "") ||
- ((mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO) &&
- (mForceUse[AudioSystem::FOR_RECORD] != AudioSystem::FORCE_BT_SCO))) &&
- ((mPhoneState != AudioSystem::MODE_IN_CALL) &&
- (mPhoneState != AudioSystem::MODE_RINGTONE))) {
-
- mpClientInterface->restoreOutput(mA2dpOutput);
- mA2dpSuspended = false;
- }
- } else {
- if (((mScoDeviceAddress != "") &&
- ((mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
- (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO))) ||
- ((mPhoneState == AudioSystem::MODE_IN_CALL) ||
- (mPhoneState == AudioSystem::MODE_RINGTONE))) {
-
- mpClientInterface->suspendOutput(mA2dpOutput);
- mA2dpSuspended = true;
- }
- }
-}
-
-
-#endif
-
-uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
-{
- uint32_t device = 0;
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
- // check the following by order of priority to request a routing change if necessary:
- // 1: we are in call or the strategy phone is active on the hardware output:
- // use device for strategy phone
- // 2: the strategy sonification is active on the hardware output:
- // use device for strategy sonification
- // 3: the strategy media is active on the hardware output:
- // use device for strategy media
- // 4: the strategy DTMF is active on the hardware output:
- // use device for strategy DTMF
- if (isInCall() ||
- outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
- device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
- device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
- device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
- device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
- }
-
- LOGV("getNewDevice() selected device %x", device);
- return device;
-}
-
-uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type stream) {
- return (uint32_t)getStrategy(stream);
-}
-
-uint32_t AudioPolicyManagerBase::getDevicesForStream(AudioSystem::stream_type stream) {
- uint32_t devices;
- // By checking the range of stream before calling getStrategy, we avoid
- // getStrategy's behavior for invalid streams. getStrategy would do a LOGE
- // and then return STRATEGY_MEDIA, but we want to return the empty set.
- if (stream < (AudioSystem::stream_type) 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
- devices = 0;
- } else {
- AudioPolicyManagerBase::routing_strategy strategy = getStrategy(stream);
- devices = getDeviceForStrategy(strategy, true);
- }
- return devices;
-}
-
-AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
- AudioSystem::stream_type stream) {
- // stream to strategy mapping
- switch (stream) {
- case AudioSystem::VOICE_CALL:
- case AudioSystem::BLUETOOTH_SCO:
- return STRATEGY_PHONE;
- case AudioSystem::RING:
- case AudioSystem::NOTIFICATION:
- case AudioSystem::ALARM:
- case AudioSystem::ENFORCED_AUDIBLE:
- return STRATEGY_SONIFICATION;
- case AudioSystem::DTMF:
- return STRATEGY_DTMF;
- default:
- LOGE("unknown stream type");
- case AudioSystem::SYSTEM:
- // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
- // while key clicks are played produces a poor result
- case AudioSystem::TTS:
- case AudioSystem::MUSIC:
- return STRATEGY_MEDIA;
- }
-}
-
-uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
-{
- uint32_t device = 0;
-
- if (fromCache) {
- LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
- return mDeviceForStrategy[strategy];
- }
-
- switch (strategy) {
- case STRATEGY_DTMF:
- if (!isInCall()) {
- // when off call, DTMF strategy follows the same rules as MEDIA strategy
- device = getDeviceForStrategy(STRATEGY_MEDIA, false);
- break;
- }
- // when in call, DTMF and PHONE strategies follow the same rules
- // FALL THROUGH
-
- case STRATEGY_PHONE:
- // for phone strategy, we first consider the forced use and then the available devices by order
- // of priority
- switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
- case AudioSystem::FORCE_BT_SCO:
- if (!isInCall() || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
- if (device) break;
- // if SCO device is requested but no SCO device is available, fall back to default case
- // FALL THROUGH
-
- default: // FORCE_NONE
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
- if (device) break;
-#ifdef WITH_A2DP
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
- if (!isInCall() && !mA2dpSuspended) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- if (device) break;
- }
-#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
- if (device == 0) {
- LOGE("getDeviceForStrategy() earpiece device not found");
- }
- break;
-
- case AudioSystem::FORCE_SPEAKER:
-#ifdef WITH_A2DP
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
- // A2DP speaker when forcing to speaker output
- if (!isInCall() && !mA2dpSuspended) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- if (device) break;
- }
-#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- break;
- }
- break;
-
- case STRATEGY_SONIFICATION:
-
- // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
- // handleIncallSonification().
- if (isInCall()) {
- device = getDeviceForStrategy(STRATEGY_PHONE, false);
- break;
- }
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- // The second device used for sonification is the same as the device used by media strategy
- // FALL THROUGH
-
- case STRATEGY_MEDIA: {
- uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
- }
-#ifdef WITH_A2DP
- if ((mA2dpOutput != 0) && !mA2dpSuspended &&
- (strategy != STRATEGY_SONIFICATION || a2dpUsedForSonification())) {
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- }
- }
-#endif
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- }
-
- // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
- device |= device2;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- } break;
-
- default:
- LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
- break;
- }
-
- LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
- return device;
-}
-
-void AudioPolicyManagerBase::updateDeviceForStrategy()
-{
- for (int i = 0; i < NUM_STRATEGIES; i++) {
- mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
- }
-}
-
-void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
-{
- LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
-
-
- if (outputDesc->isDuplicated()) {
- setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
- setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
- return;
- }
-#ifdef WITH_A2DP
- // filter devices according to output selected
- if (output == mA2dpOutput) {
- device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
- } else {
- device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
- }
-#endif
-
- uint32_t prevDevice = (uint32_t)outputDesc->device();
- // Do not change the routing if:
- // - the requestede device is 0
- // - the requested device is the same as current device and force is not specified.
- // Doing this check here allows the caller to call setOutputDevice() without conditions
- if ((device == 0 || device == prevDevice) && !force) {
- LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
- return;
- }
-
- outputDesc->mDevice = device;
- // mute media streams if both speaker and headset are selected
- if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
- setStrategyMute(STRATEGY_MEDIA, true, output);
- // wait for the PCM output buffers to empty before proceeding with the rest of the command
- usleep(outputDesc->mLatency*2*1000);
- }
-
- // do the routing
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)device);
- mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
- // update stream volumes according to new device
- applyStreamVolumes(output, device, delayMs);
-
- // if changing from a combined headset + speaker route, unmute media streams
- if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
- setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
- }
-}
-
-uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
-{
- uint32_t device;
-
- switch(inputSource) {
- case AUDIO_SOURCE_DEFAULT:
- case AUDIO_SOURCE_MIC:
- case AUDIO_SOURCE_VOICE_RECOGNITION:
- case AUDIO_SOURCE_VOICE_COMMUNICATION:
- if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
- mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
- } else {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
- }
- break;
- case AUDIO_SOURCE_CAMCORDER:
- if (hasBackMicrophone()) {
- device = AudioSystem::DEVICE_IN_BACK_MIC;
- } else {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
- }
- break;
- case AUDIO_SOURCE_VOICE_UPLINK:
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- case AUDIO_SOURCE_VOICE_CALL:
- device = AudioSystem::DEVICE_IN_VOICE_CALL;
- break;
- default:
- LOGW("getInput() invalid input source %d", inputSource);
- device = 0;
- break;
- }
- LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
- return device;
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
-{
- for (size_t i = 0; i < mInputs.size(); i++) {
- if (mInputs.valueAt(i)->mRefCount > 0) {
- return mInputs.keyAt(i);
- }
- }
- return 0;
-}
-
-float AudioPolicyManagerBase::volIndexToAmpl(uint32_t device, const StreamDescriptor& streamDesc,
- int indexInUi) {
- // the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + streamDesc.mVolIndex[StreamDescriptor::VOLMAX] -
- streamDesc.mVolIndex[StreamDescriptor::VOLMIN];
- int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
- (streamDesc.mIndexMax - streamDesc.mIndexMin);
-
- // find what part of the curve this index volume belongs to, or if it's out of bounds
- int segment = 0;
- if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLMIN]) { // out of bounds
- return 0.0f;
- } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE1]) {
- segment = 0;
- } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE2]) {
- segment = 1;
- } else if (volIdx <= streamDesc.mVolIndex[StreamDescriptor::VOLMAX]) {
- segment = 2;
- } else { // out of bounds
- return 1.0f;
- }
-
- // linear interpolation in the attenuation table in dB
- float decibels = streamDesc.mVolDbAtt[segment] +
- ((float)(volIdx - streamDesc.mVolIndex[segment])) *
- ( (streamDesc.mVolDbAtt[segment+1] - streamDesc.mVolDbAtt[segment]) /
- ((float)(streamDesc.mVolIndex[segment+1] - streamDesc.mVolIndex[segment])) );
-
- float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
-
- LOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
- streamDesc.mVolIndex[segment], volIdx, streamDesc.mVolIndex[segment+1],
- streamDesc.mVolDbAtt[segment], decibels, streamDesc.mVolDbAtt[segment+1],
- amplification);
-
- return amplification;
-}
-
-void AudioPolicyManagerBase::initializeVolumeCurves() {
- // initialize the volume curves to a (-49.5 - 0 dB) attenuation in 0.5dB steps
- for (int i=0 ; i< AudioSystem::NUM_STREAM_TYPES ; i++) {
- mStreams[i].mVolIndex[StreamDescriptor::VOLMIN] = 1;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLMIN] = -49.5f;
- mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE1] = 33;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -33.5f;
- mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE2] = 66;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f;
- // here we use 100 steps to avoid rounding errors
- // when computing the volume in volIndexToAmpl()
- mStreams[i].mVolIndex[StreamDescriptor::VOLMAX] = 100;
- mStreams[i].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f;
- }
-
- // Modification for music: more attenuation for lower volumes, finer steps at high volumes
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMIN] = 1;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMIN] = -58.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE1] = 20;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -40.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE2] = 60;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f;
- mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMAX] = 100;
- mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f;
-}
-
-float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
-{
- float volume = 1.0;
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
- StreamDescriptor &streamDesc = mStreams[stream];
-
- if (device == 0) {
- device = outputDesc->device();
- }
-
- // if volume is not 0 (not muted), force media volume to max on digital output
- if (stream == AudioSystem::MUSIC &&
- index != mStreams[stream].mIndexMin &&
- device == AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
- return 1.0;
- }
-
- volume = volIndexToAmpl(device, streamDesc, index);
-
- // if a headset is connected, apply the following rules to ring tones and notifications
- // to avoid sound level bursts in user's ears:
- // - always attenuate ring tones and notifications volume by 6dB
- // - if music is playing, always limit the volume to current music volume,
- // with a minimum threshold at -36dB so that notification is always perceived.
- if ((device &
- (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
- AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AudioSystem::DEVICE_OUT_WIRED_HEADSET |
- AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
- ((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) ||
- (stream == AudioSystem::SYSTEM)) &&
- streamDesc.mCanBeMuted) {
- volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
- // when the phone is ringing we must consider that music could have been paused just before
- // by the music application and behave as if music was active if the last music track was
- // just stopped
- if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
- float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
- float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
- if (volume > minVol) {
- volume = minVol;
- LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
- }
- }
- }
-
- return volume;
-}
-
-status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
-{
-
- // do not change actual stream volume if the stream is muted
- if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
- LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
- return NO_ERROR;
- }
-
- // do not change in call volume if bluetooth is connected and vice versa
- if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
- (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
- LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
- stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
- return INVALID_OPERATION;
- }
-
- float volume = computeVolume(stream, index, output, device);
- // We actually change the volume if:
- // - the float value returned by computeVolume() changed
- // - the force flag is set
- if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
- force) {
- mOutputs.valueFor(output)->mCurVolume[stream] = volume;
- LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
- if (stream == AudioSystem::VOICE_CALL ||
- stream == AudioSystem::DTMF ||
- stream == AudioSystem::BLUETOOTH_SCO) {
- // offset value to reflect actual hardware volume that never reaches 0
- // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
- volume = 0.01 + 0.99 * volume;
- // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
- // enabled
- if (stream == AudioSystem::BLUETOOTH_SCO) {
- mpClientInterface->setStreamVolume(AudioSystem::VOICE_CALL, volume, output, delayMs);
- }
- }
-
- mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
- }
-
- if (stream == AudioSystem::VOICE_CALL ||
- stream == AudioSystem::BLUETOOTH_SCO) {
- float voiceVolume;
- // Force voice volume to max for bluetooth SCO as volume is managed by the headset
- if (stream == AudioSystem::VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
- } else {
- voiceVolume = 1.0;
- }
-
- if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
- mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
- mLastVoiceVolume = voiceVolume;
- }
- }
-
- return NO_ERROR;
-}
-
-void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs, bool force)
-{
- LOGV("applyStreamVolumes() for output %d and device %x", output, device);
-
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs, force);
- }
-}
-
-void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs)
-{
- LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- if (getStrategy((AudioSystem::stream_type)stream) == strategy) {
- setStreamMute(stream, on, output, delayMs);
- }
- }
-}
-
-void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
-{
- StreamDescriptor &streamDesc = mStreams[stream];
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
-
- LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
-
- if (on) {
- if (outputDesc->mMuteCount[stream] == 0) {
- if (streamDesc.mCanBeMuted) {
- checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
- }
- }
- // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
- outputDesc->mMuteCount[stream]++;
- } else {
- if (outputDesc->mMuteCount[stream] == 0) {
- LOGW("setStreamMute() unmuting non muted stream!");
- return;
- }
- if (--outputDesc->mMuteCount[stream] == 0) {
- checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs);
- }
- }
-}
-
-void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange)
-{
- // if the stream pertains to sonification strategy and we are in call we must
- // mute the stream if it is low visibility. If it is high visibility, we must play a tone
- // in the device used for phone strategy and play the tone if the selected device does not
- // interfere with the device used for phone strategy
- // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
- // many times as there are active tracks on the output
-
- if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
- LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
- stream, starting, outputDesc->mDevice, stateChange);
- if (outputDesc->mRefCount[stream]) {
- int muteCount = 1;
- if (stateChange) {
- muteCount = outputDesc->mRefCount[stream];
- }
- if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
- LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount);
- for (int i = 0; i < muteCount; i++) {
- setStreamMute(stream, starting, mHardwareOutput);
- }
- } else {
- LOGV("handleIncallSonification() high visibility");
- if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) {
- LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount);
- for (int i = 0; i < muteCount; i++) {
- setStreamMute(stream, starting, mHardwareOutput);
- }
- }
- if (starting) {
- mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
- } else {
- mpClientInterface->stopTone();
- }
- }
- }
- }
-}
-
-bool AudioPolicyManagerBase::isInCall()
-{
- return isStateInCall(mPhoneState);
-}
-
-bool AudioPolicyManagerBase::isStateInCall(int state) {
- return ((state == AudioSystem::MODE_IN_CALL) ||
- (state == AudioSystem::MODE_IN_COMMUNICATION));
-}
-
-bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::output_flags flags,
- uint32_t device)
-{
- return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format !=0 && !AudioSystem::isLinearPCM(format)));
-}
-
-uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad()
-{
- return MAX_EFFECTS_CPU_LOAD;
-}
-
-uint32_t AudioPolicyManagerBase::getMaxEffectsMemory()
-{
- return MAX_EFFECTS_MEMORY;
-}
-
-// --- AudioOutputDescriptor class implementation
-
-AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
- : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
- mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
-{
- // clear usage count for all stream types
- for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- mRefCount[i] = 0;
- mCurVolume[i] = -1.0;
- mMuteCount[i] = 0;
- mStopTime[i] = 0;
- }
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device()
-{
- uint32_t device = 0;
- if (isDuplicated()) {
- device = mOutput1->mDevice | mOutput2->mDevice;
- } else {
- device = mDevice;
- }
- return device;
-}
-
-void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
-{
- // forward usage count change to attached outputs
- if (isDuplicated()) {
- mOutput1->changeRefCount(stream, delta);
- mOutput2->changeRefCount(stream, delta);
- }
- if ((delta + (int)mRefCount[stream]) < 0) {
- LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
- mRefCount[stream] = 0;
- return;
- }
- mRefCount[stream] += delta;
- LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
-{
- uint32_t refcount = 0;
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- refcount += mRefCount[i];
- }
- return refcount;
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy)
-{
- uint32_t refCount = 0;
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- if (getStrategy((AudioSystem::stream_type)i) == strategy) {
- refCount += mRefCount[i];
- }
- }
- return refCount;
-}
-
-status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
- result.append(buffer);
- snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
- result.append(buffer);
- snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", device());
- result.append(buffer);
- snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
- result.append(buffer);
- for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
- result.append(buffer);
- }
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-// --- AudioInputDescriptor class implementation
-
-AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor()
- : mSamplingRate(0), mFormat(0), mChannels(0),
- mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
-{
-}
-
-status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
- result.append(buffer);
- snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-// --- StreamDescriptor class implementation
-
-void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size)
-{
- snprintf(buffer, size, " %02d %02d %02d %d\n",
- mIndexMin,
- mIndexMax,
- mIndexCur,
- mCanBeMuted);
-}
-
-// --- EffectDescriptor class implementation
-
-status_t AudioPolicyManagerBase::EffectDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " Output: %d\n", mOutput);
- result.append(buffer);
- snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
- result.append(buffer);
- snprintf(buffer, SIZE, " Session: %d\n", mSession);
- result.append(buffer);
- snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-
-
-}; // namespace android
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index b614c48..eebc1b3 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -30,11 +30,15 @@
#include <utils/String16.h>
#include <utils/threads.h>
#include "AudioPolicyService.h"
-#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <cutils/properties.h>
#include <dlfcn.h>
#include <hardware_legacy/power.h>
+#include <hardware/hardware.h>
+#include <hardware/audio.h>
+#include <hardware/audio_policy.h>
+#include <hardware/audio_policy_hal.h>
+
// ----------------------------------------------------------------------------
// the sim build doesn't have gettid
@@ -44,7 +48,6 @@
namespace android {
-
static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
@@ -61,12 +64,19 @@ static bool checkPermission() {
return ok;
}
+namespace {
+ extern struct audio_policy_service_ops aps_ops;
+};
+
// ----------------------------------------------------------------------------
AudioPolicyService::AudioPolicyService()
- : BnAudioPolicyService() , mpPolicyManager(NULL)
+ : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
char value[PROPERTY_VALUE_MAX];
+ const struct hw_module_t *module;
+ int forced_val;
+ int rc;
Mutex::Autolock _l(mLock);
@@ -75,33 +85,32 @@ AudioPolicyService::AudioPolicyService()
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
-#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
- mpPolicyManager = new AudioPolicyManagerBase(this);
- LOGV("build for GENERIC_AUDIO - using generic audio policy");
-#else
- // if running in emulation - use the emulator driver
- if (property_get("ro.kernel.qemu", value, 0)) {
- LOGV("Running in emulation - using generic audio policy");
- mpPolicyManager = new AudioPolicyManagerBase(this);
- }
- else {
- LOGV("Using hardware specific audio policy");
- mpPolicyManager = createAudioPolicyManager(this);
- }
-#endif
+ /* instantiate the audio policy manager */
+ rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
+ if (rc)
+ return;
- if ((mpPolicyManager != NULL) && (mpPolicyManager->initCheck() != NO_ERROR)) {
- delete mpPolicyManager;
- mpPolicyManager = NULL;
- }
+ rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
+ LOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
+ if (rc)
+ return;
- if (mpPolicyManager == NULL) {
- LOGE("Could not create AudioPolicyManager");
- } else {
- // load properties
- property_get("ro.camera.sound.forced", value, "0");
- mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
- }
+ rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
+ &mpAudioPolicy);
+ LOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
+ if (rc)
+ return;
+
+ rc = mpAudioPolicy->init_check(mpAudioPolicy);
+ LOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
+ if (rc)
+ return;
+
+ property_get("ro.camera.sound.forced", value, "0");
+ forced_val = strtol(value, NULL, 0);
+ mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
+
+ LOGI("Loaded audio policy from %s (%s)", module->name, module->id);
}
AudioPolicyService::~AudioPolicyService()
@@ -111,57 +120,59 @@ AudioPolicyService::~AudioPolicyService()
mAudioCommandThread->exit();
mAudioCommandThread.clear();
- if (mpPolicyManager) {
- delete mpPolicyManager;
- }
+ if (mpAudioPolicy && mpAudioPolicyDev)
+ mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
+ if (mpAudioPolicyDev)
+ audio_policy_dev_close(mpAudioPolicyDev);
}
-
-status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
+status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
const char *device_address)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
+ if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
return BAD_VALUE;
}
- if (state != AudioSystem::DEVICE_STATE_AVAILABLE &&
- state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
+ if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
+ state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
return BAD_VALUE;
}
LOGV("setDeviceConnectionState() tid %d", gettid());
Mutex::Autolock _l(mLock);
- return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
+ return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
+ state, device_address);
}
-AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(
- AudioSystem::audio_devices device,
+audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
+ audio_devices_t device,
const char *device_address)
{
- if (mpPolicyManager == NULL) {
- return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+ if (mpAudioPolicy == NULL) {
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
if (!checkPermission()) {
- return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
- return mpPolicyManager->getDeviceConnectionState(device, device_address);
+ return mpAudioPolicy->get_device_connection_state(mpAudioPolicy, device,
+ device_address);
}
status_t AudioPolicyService::setPhoneState(int state)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (state < 0 || state >= AudioSystem::NUM_MODES) {
+ if (state < 0 || state >= AUDIO_MODE_CNT) {
return BAD_VALUE;
}
@@ -171,215 +182,215 @@ status_t AudioPolicyService::setPhoneState(int state)
AudioSystem::setMode(state);
Mutex::Autolock _l(mLock);
- mpPolicyManager->setPhoneState(state);
+ mpAudioPolicy->set_phone_state(mpAudioPolicy, state);
return NO_ERROR;
}
status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- mpPolicyManager->setRingerMode(mode, mask);
+ mpAudioPolicy->set_ringer_mode(mpAudioPolicy, mode, mask);
return NO_ERROR;
}
-status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage,
- AudioSystem::forced_config config)
+status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+ if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
return BAD_VALUE;
}
- if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
+ if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
return BAD_VALUE;
}
LOGV("setForceUse() tid %d", gettid());
Mutex::Autolock _l(mLock);
- mpPolicyManager->setForceUse(usage, config);
+ mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config);
return NO_ERROR;
}
-AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
+audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage)
{
- if (mpPolicyManager == NULL) {
- return AudioSystem::FORCE_NONE;
+ if (mpAudioPolicy == NULL) {
+ return AUDIO_POLICY_FORCE_NONE;
}
if (!checkPermission()) {
- return AudioSystem::FORCE_NONE;
+ return AUDIO_POLICY_FORCE_NONE;
}
- if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
- return AudioSystem::FORCE_NONE;
+ if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
+ return AUDIO_POLICY_FORCE_NONE;
}
- return mpPolicyManager->getForceUse(usage);
+ return mpAudioPolicy->get_force_use(mpAudioPolicy, usage);
}
-audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
+audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- AudioSystem::output_flags flags)
+ audio_policy_output_flags_t flags)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return 0;
}
LOGV("getOutput() tid %d", gettid());
Mutex::Autolock _l(mLock);
- return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
+ return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channels, flags);
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
LOGV("startOutput() tid %d", gettid());
Mutex::Autolock _l(mLock);
- return mpPolicyManager->startOutput(output, stream, session);
+ return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
}
status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
LOGV("stopOutput() tid %d", gettid());
Mutex::Autolock _l(mLock);
- return mpPolicyManager->stopOutput(output, stream, session);
+ return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
}
void AudioPolicyService::releaseOutput(audio_io_handle_t output)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return;
}
LOGV("releaseOutput() tid %d", gettid());
Mutex::Autolock _l(mLock);
- mpPolicyManager->releaseOutput(output);
+ mpAudioPolicy->release_output(mpAudioPolicy, output);
}
audio_io_handle_t AudioPolicyService::getInput(int inputSource,
uint32_t samplingRate,
uint32_t format,
uint32_t channels,
- AudioSystem::audio_in_acoustics acoustics)
+ audio_in_acoustics_t acoustics)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return 0;
}
Mutex::Autolock _l(mLock);
- return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
+ return mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, format, channels, acoustics);
}
status_t AudioPolicyService::startInput(audio_io_handle_t input)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mpPolicyManager->startInput(input);
+ return mpAudioPolicy->start_input(mpAudioPolicy, input);
}
status_t AudioPolicyService::stopInput(audio_io_handle_t input)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mpPolicyManager->stopInput(input);
+ return mpAudioPolicy->stop_input(mpAudioPolicy, input);
}
void AudioPolicyService::releaseInput(audio_io_handle_t input)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return;
}
Mutex::Autolock _l(mLock);
- mpPolicyManager->releaseInput(input);
+ mpAudioPolicy->release_input(mpAudioPolicy, input);
}
-status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
+status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
- mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
+ mpAudioPolicy->init_stream_volume(mpAudioPolicy, stream, indexMin, indexMax);
return NO_ERROR;
}
-status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, int index)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
- return mpPolicyManager->setStreamVolumeIndex(stream, index);
+ return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
}
-status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, int *index)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+ if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
- return mpPolicyManager->getStreamVolumeIndex(stream, index);
+ return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
}
-uint32_t AudioPolicyService::getStrategyForStream(AudioSystem::stream_type stream)
+uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return 0;
}
- return mpPolicyManager->getStrategyForStream(stream);
+ return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
}
-uint32_t AudioPolicyService::getDevicesForStream(AudioSystem::stream_type stream)
+uint32_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return 0;
}
- return mpPolicyManager->getDevicesForStream(stream);
+ return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
}
audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
- return mpPolicyManager->getOutputForEffect(desc);
+ return mpAudioPolicy->get_output_for_effect(mpAudioPolicy, desc);
}
status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
@@ -388,27 +399,27 @@ status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
int session,
int id)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- return mpPolicyManager->registerEffect(desc, output, strategy, session, id);
+ return mpAudioPolicy->register_effect(mpAudioPolicy, desc, output, strategy, session, id);
}
status_t AudioPolicyService::unregisterEffect(int id)
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- return mpPolicyManager->unregisterEffect(id);
+ return mpAudioPolicy->unregister_effect(mpAudioPolicy, id);
}
bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
{
- if (mpPolicyManager == NULL) {
+ if (mpAudioPolicy == NULL) {
return 0;
}
Mutex::Autolock _l(mLock);
- return mpPolicyManager->isStreamActive(stream, inPastMs);
+ return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
@@ -435,7 +446,7 @@ status_t AudioPolicyService::dumpInternals(int fd)
char buffer[SIZE];
String8 result;
- snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
+ snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
result.append(buffer);
snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
result.append(buffer);
@@ -465,8 +476,8 @@ status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
mTonePlaybackThread->dump(fd);
}
- if (mpPolicyManager) {
- mpPolicyManager->dump(fd);
+ if (mpAudioPolicy) {
+ mpAudioPolicy->dump(mpAudioPolicy, fd);
}
if (locked) mLock.unlock();
@@ -495,154 +506,6 @@ status_t AudioPolicyService::onTransact(
}
-// ----------------------------------------------------------------------------
-// AudioPolicyClientInterface implementation
-// ----------------------------------------------------------------------------
-
-
-audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- AudioSystem::output_flags flags)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openOutput() could not get AudioFlinger");
- return 0;
- }
-
- return af->openOutput(pDevices,
- pSamplingRate,
- (uint32_t *)pFormat,
- pChannels,
- pLatencyMs,
- flags);
-}
-
-audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1,
- audio_io_handle_t output2)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openDuplicateOutput() could not get AudioFlinger");
- return 0;
- }
- return af->openDuplicateOutput(output1, output2);
-}
-
-status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->closeOutput(output);
-}
-
-
-status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("suspendOutput() could not get AudioFlinger");
- return PERMISSION_DENIED;
- }
-
- return af->suspendOutput(output);
-}
-
-status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("restoreOutput() could not get AudioFlinger");
- return PERMISSION_DENIED;
- }
-
- return af->restoreOutput(output);
-}
-
-audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openInput() could not get AudioFlinger");
- return 0;
- }
-
- return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
-}
-
-status_t AudioPolicyService::closeInput(audio_io_handle_t input)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->closeInput(input);
-}
-
-status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream,
- float volume,
- audio_io_handle_t output,
- int delayMs)
-{
- return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
-}
-
-status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream,
- audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->setStreamOutput(stream, output);
-}
-
-status_t AudioPolicyService::moveEffects(int session, audio_io_handle_t srcOutput,
- audio_io_handle_t dstOutput)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->moveEffects(session, (int)srcOutput, (int)dstOutput);
-}
-
-void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
- const String8& keyValuePairs,
- int delayMs)
-{
- mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
-}
-
-String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
-{
- String8 result = AudioSystem::getParameters(ioHandle, keys);
- return result;
-}
-
-status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone,
- AudioSystem::stream_type stream)
-{
- mTonePlaybackThread->startToneCommand(tone, stream);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::stopTone()
-{
- mTonePlaybackThread->stopToneCommand();
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
-{
- return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
-}
-
// ----------- AudioPolicyService::AudioCommandThread implementation ----------
AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
@@ -859,7 +722,7 @@ status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
}
status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
- const String8& keyValuePairs,
+ const char *keyValuePairs,
int delayMs)
{
status_t status = NO_ERROR;
@@ -868,7 +731,7 @@ status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
command->mCommand = SET_PARAMETERS;
ParametersData *data = new ParametersData();
data->mIO = ioHandle;
- data->mKeyValuePairs = keyValuePairs;
+ data->mKeyValuePairs = String8(keyValuePairs);
command->mParam = data;
if (delayMs == 0) {
command->mWaitStatus = true;
@@ -878,7 +741,7 @@ status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
Mutex::Autolock _l(mLock);
insertCommand_l(command, delayMs);
LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
- keyValuePairs.string(), ioHandle, delayMs);
+ keyValuePairs, ioHandle, delayMs);
mWaitWorkCV.signal();
if (command->mWaitStatus) {
command->mCond.wait(mLock);
@@ -1023,4 +886,226 @@ void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, si
mParam);
}
+/******* helpers for the service_ops callbacks defined below *********/
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
+ const char *keyValuePairs,
+ int delayMs)
+{
+ mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs,
+ delayMs);
+}
+
+int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
+ float volume,
+ audio_io_handle_t output,
+ int delayMs)
+{
+ return (int)mAudioCommandThread->volumeCommand((int)stream, volume,
+ (int)output, delayMs);
+}
+
+int AudioPolicyService::startTone(audio_policy_tone_t tone,
+ audio_stream_type_t stream)
+{
+ if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION)
+ LOGE("startTone: illegal tone requested (%d)", tone);
+ if (stream != AUDIO_STREAM_VOICE_CALL)
+ LOGE("startTone: illegal stream (%d) requested for tone %d", stream,
+ tone);
+ mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
+ AUDIO_STREAM_VOICE_CALL);
+ return 0;
+}
+
+int AudioPolicyService::stopTone()
+{
+ mTonePlaybackThread->stopToneCommand();
+ return 0;
+}
+
+int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+ return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
+
+/* implementation of the interface to the policy manager */
+extern "C" {
+
+static audio_io_handle_t aps_open_output(void *service,
+ uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL) {
+ LOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,
+ pLatencyMs, flags);
+}
+
+static audio_io_handle_t aps_open_dup_output(void *service,
+ audio_io_handle_t output1,
+ audio_io_handle_t output2)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL) {
+ LOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+ return af->openDuplicateOutput(output1, output2);
+}
+
+static int aps_close_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL)
+ return PERMISSION_DENIED;
+
+ return af->closeOutput(output);
+}
+
+static int aps_suspend_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL) {
+ LOGW("%s: could not get AudioFlinger", __func__);
+ return PERMISSION_DENIED;
+ }
+
+ return af->suspendOutput(output);
+}
+
+static int aps_restore_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL) {
+ LOGW("%s: could not get AudioFlinger", __func__);
+ return PERMISSION_DENIED;
+ }
+
+ return af->restoreOutput(output);
+}
+
+static audio_io_handle_t aps_open_input(void *service,
+ uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ uint32_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t acoustics)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL) {
+ LOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
+ acoustics);
+}
+
+static int aps_close_input(void *service, audio_io_handle_t input)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL)
+ return PERMISSION_DENIED;
+
+ return af->closeInput(input);
+}
+
+static int aps_set_stream_output(void *service, audio_stream_type_t stream,
+ audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL)
+ return PERMISSION_DENIED;
+
+ return af->setStreamOutput(stream, output);
+}
+
+static int aps_move_effects(void *service, int session,
+ audio_io_handle_t src_output,
+ audio_io_handle_t dst_output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == NULL)
+ return PERMISSION_DENIED;
+
+ return af->moveEffects(session, (int)src_output, (int)dst_output);
+}
+
+static char * aps_get_parameters(void *service, audio_io_handle_t io_handle,
+ const char *keys)
+{
+ String8 result = AudioSystem::getParameters(io_handle, String8(keys));
+ return strdup(result.string());
+}
+
+static void aps_set_parameters(void *service, audio_io_handle_t io_handle,
+ const char *kv_pairs, int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ audioPolicyService->setParameters(io_handle, kv_pairs, delay_ms);
+}
+
+static int aps_set_stream_volume(void *service, audio_stream_type_t stream,
+ float volume, audio_io_handle_t output,
+ int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->setStreamVolume(stream, volume, output,
+ delay_ms);
+}
+
+static int aps_start_tone(void *service, audio_policy_tone_t tone,
+ audio_stream_type_t stream)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->startTone(tone, stream);
+}
+
+static int aps_stop_tone(void *service)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->stopTone();
+}
+
+static int aps_set_voice_volume(void *service, float volume, int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->setVoiceVolume(volume, delay_ms);
+}
+
+}; // extern "C"
+
+namespace {
+ struct audio_policy_service_ops aps_ops = {
+ open_output : aps_open_output,
+ open_duplicate_output : aps_open_dup_output,
+ close_output : aps_close_output,
+ suspend_output : aps_suspend_output,
+ restore_output : aps_restore_output,
+ open_input : aps_open_input,
+ close_input : aps_close_input,
+ set_stream_volume : aps_set_stream_volume,
+ set_stream_output : aps_set_stream_output,
+ set_parameters : aps_set_parameters,
+ get_parameters : aps_get_parameters,
+ start_tone : aps_start_tone,
+ stop_tone : aps_stop_tone,
+ set_voice_volume : aps_set_voice_volume,
+ move_effects : aps_move_effects,
+ };
+}; // namespace <unnamed>
+
}; // namespace android
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index faad893..01e592b 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -18,11 +18,14 @@
#define ANDROID_AUDIOPOLICYSERVICE_H
#include <media/IAudioPolicyService.h>
-#include <hardware_legacy/AudioPolicyInterface.h>
#include <media/ToneGenerator.h>
#include <utils/Vector.h>
#include <binder/BinderService.h>
+#include <hardware/audio.h>
+#include <hardware/audio_policy.h>
+#include <hardware/audio_policy_hal.h>
+
namespace android {
class String8;
@@ -32,7 +35,7 @@ class String8;
class AudioPolicyService :
public BinderService<AudioPolicyService>,
public BnAudioPolicyService,
- public AudioPolicyClientInterface,
+// public AudioPolicyClientInterface,
public IBinder::DeathRecipient
{
friend class BinderService<AudioPolicyService>;
@@ -47,46 +50,46 @@ public:
// BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
//
- virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
const char *device_address);
- virtual AudioSystem::device_connection_state getDeviceConnectionState(
- AudioSystem::audio_devices device,
+ virtual audio_policy_dev_state_t getDeviceConnectionState(
+ audio_devices_t device,
const char *device_address);
virtual status_t setPhoneState(int state);
virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
- virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
- virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
- virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+ virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = 0,
- AudioSystem::output_flags flags =
- AudioSystem::OUTPUT_FLAG_INDIRECT);
+ audio_policy_output_flags_t flags =
+ AUDIO_POLICY_OUTPUT_FLAG_INDIRECT);
virtual status_t startOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0);
virtual status_t stopOutput(audio_io_handle_t output,
- AudioSystem::stream_type stream,
+ audio_stream_type_t stream,
int session = 0);
virtual void releaseOutput(audio_io_handle_t output);
virtual audio_io_handle_t getInput(int inputSource,
uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
+ uint32_t format = AUDIO_FORMAT_DEFAULT,
uint32_t channels = 0,
- AudioSystem::audio_in_acoustics acoustics =
- (AudioSystem::audio_in_acoustics)0);
+ audio_in_acoustics_t acoustics =
+ (audio_in_acoustics_t)0);
virtual status_t startInput(audio_io_handle_t input);
virtual status_t stopInput(audio_io_handle_t input);
virtual void releaseInput(audio_io_handle_t input);
- virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);
- virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
- virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, int index);
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
- virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream);
- virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream);
+ virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
+ virtual uint32_t getDevicesForStream(audio_stream_type_t stream);
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
virtual status_t registerEffect(effect_descriptor_t *desc,
@@ -107,40 +110,21 @@ public:
virtual void binderDied(const wp<IBinder>& who);
//
- // AudioPolicyClientInterface
+ // Helpers for the struct audio_policy_service_ops implementation.
+ // This is used by the audio policy manager for certain operations that
+ // are implemented by the policy service.
//
- virtual audio_io_handle_t openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- AudioSystem::output_flags flags);
- virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
- audio_io_handle_t output2);
- virtual status_t closeOutput(audio_io_handle_t output);
- virtual status_t suspendOutput(audio_io_handle_t output);
- virtual status_t restoreOutput(audio_io_handle_t output);
- virtual audio_io_handle_t openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics);
- virtual status_t closeInput(audio_io_handle_t input);
- virtual status_t setStreamVolume(AudioSystem::stream_type stream,
+ virtual void setParameters(audio_io_handle_t ioHandle,
+ const char *keyValuePairs,
+ int delayMs);
+
+ virtual status_t setStreamVolume(audio_stream_type_t stream,
float volume,
audio_io_handle_t output,
int delayMs = 0);
- virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
- virtual void setParameters(audio_io_handle_t ioHandle,
- const String8& keyValuePairs,
- int delayMs = 0);
- virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
- virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
+ virtual status_t startTone(audio_policy_tone_t tone, audio_stream_type_t stream);
virtual status_t stopTone();
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
- virtual status_t moveEffects(int session,
- audio_io_handle_t srcOutput,
- audio_io_handle_t dstOutput);
private:
AudioPolicyService();
@@ -180,7 +164,7 @@ private:
void startToneCommand(int type = 0, int stream = 0);
void stopToneCommand();
status_t volumeCommand(int stream, float volume, int output, int delayMs = 0);
- status_t parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+ status_t parametersCommand(int ioHandle, const char *keyValuePairs, int delayMs = 0);
status_t voiceVolumeCommand(float volume, int delayMs = 0);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
@@ -240,9 +224,11 @@ private:
mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing
// device connection state or routing
- AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread
+
+ struct audio_policy_device *mpAudioPolicyDev;
+ struct audio_policy *mpAudioPolicy;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index b52fc69..e35435e 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -1,38 +1,5 @@
LOCAL_PATH:= $(call my-dir)
-# Set USE_CAMERA_STUB if you don't want to use the hardware camera.
-
-# force these builds to use camera stub only
-ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
- USE_CAMERA_STUB:=true
-endif
-
-ifeq ($(USE_CAMERA_STUB),)
- USE_CAMERA_STUB:=false
-endif
-
-ifeq ($(USE_CAMERA_STUB),true)
-#
-# libcamerastub
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- CameraHardwareStub.cpp \
- FakeCamera.cpp
-
-LOCAL_MODULE:= libcamerastub
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_CFLAGS += -DSINGLE_PROCESS
-endif
-
-LOCAL_SHARED_LIBRARIES:= libui
-
-include $(BUILD_STATIC_LIBRARY)
-endif # USE_CAMERA_STUB
-
#
# libcameraservice
#
@@ -49,19 +16,9 @@ LOCAL_SHARED_LIBRARIES:= \
libcutils \
libmedia \
libcamera_client \
- libsurfaceflinger_client \
- libgui
+ libgui \
+ libhardware
LOCAL_MODULE:= libcameraservice
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_CFLAGS += -DSINGLE_PROCESS
-endif
-
-ifeq ($(USE_CAMERA_STUB), true)
-LOCAL_STATIC_LIBRARIES += libcamerastub
-else
-LOCAL_SHARED_LIBRARIES += libcamera
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
new file mode 100644
index 0000000..f9fa30e
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2008 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 ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
+
+#include <binder/IMemory.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/RefBase.h>
+#include <surfaceflinger/ISurface.h>
+#include <ui/android_native_buffer.h>
+#include <ui/GraphicBuffer.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <system/window.h>
+#include <hardware/camera.h>
+
+namespace android {
+
+typedef void (*notify_callback)(int32_t msgType,
+ int32_t ext1,
+ int32_t ext2,
+ void* user);
+
+typedef void (*data_callback)(int32_t msgType,
+ const sp<IMemory> &dataPtr,
+ void* user);
+
+typedef void (*data_callback_timestamp)(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory> &dataPtr,
+ void *user);
+
+/**
+ * CameraHardwareInterface.h defines the interface to the
+ * camera hardware abstraction layer, used for setting and getting
+ * parameters, live previewing, and taking pictures.
+ *
+ * It is a referenced counted interface with RefBase as its base class.
+ * CameraService calls openCameraHardware() to retrieve a strong pointer to the
+ * instance of this interface and may be called multiple times. The
+ * following steps describe a typical sequence:
+ *
+ * -# After CameraService calls openCameraHardware(), getParameters() and
+ * setParameters() are used to initialize the camera instance.
+ * CameraService calls getPreviewHeap() to establish access to the
+ * preview heap so it can be registered with SurfaceFlinger for
+ * efficient display updating while in preview mode.
+ * -# startPreview() is called. The camera instance then periodically
+ * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time
+ * a new preview frame is available. If data callback code needs to use
+ * this memory after returning, it must copy the data.
+ *
+ * Prior to taking a picture, CameraService calls autofocus(). When auto
+ * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification,
+ * which informs the application whether focusing was successful. The camera instance
+ * only sends this message once and it is up to the application to call autoFocus()
+ * again if refocusing is desired.
+ *
+ * CameraService calls takePicture() to request the camera instance take a
+ * picture. At this point, if a shutter, postview, raw, and/or compressed callback
+ * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME,
+ * any memory provided in a data callback must be copied if it's needed after returning.
+ */
+
+class CameraHardwareInterface : public virtual RefBase {
+public:
+ CameraHardwareInterface(hw_module_t *module, const char *name)
+ {
+ mDevice = 0;
+ mName = name;
+ LOGI("Opening camera %s, this %p", name, this);
+ int rc = module->methods->open(module, name,
+ (hw_device_t **)&mDevice);
+ if (rc != OK)
+ LOGE("Could not open camera %s: %d", name, rc);
+ initHalPreviewWindow();
+ }
+
+ ~CameraHardwareInterface()
+ {
+ LOGI("Destroying camera %s", mName.string());
+ int rc = mDevice->common.close(&mDevice->common);
+ if (rc != OK)
+ LOGE("Could not close camera %s: %d", mName.string(), rc);
+ }
+
+ /** Set the ANativeWindow to which preview frames are sent */
+ status_t setPreviewWindow(const sp<ANativeWindow>& buf)
+ {
+ LOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
+
+ if (mDevice->ops->set_preview_window) {
+ mPreviewWindow = buf;
+ mHalPreviewWindow.user = this;
+ LOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
+ &mHalPreviewWindow, mHalPreviewWindow.user);
+ return mDevice->ops->set_preview_window(mDevice,
+ buf.get() ? &mHalPreviewWindow.nw : 0);
+ }
+ return INVALID_OPERATION;
+ }
+
+ /** Set the notification and data callbacks */
+ void setCallbacks(notify_callback notify_cb,
+ data_callback data_cb,
+ data_callback_timestamp data_cb_timestamp,
+ void* user)
+ {
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mCbUser = user;
+
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+
+ if (mDevice->ops->set_callbacks) {
+ mDevice->ops->set_callbacks(mDevice,
+ __notify_cb,
+ __data_cb,
+ __data_cb_timestamp,
+ __get_memory,
+ this);
+ }
+ }
+
+ /**
+ * The following three functions all take a msgtype,
+ * which is a bitmask of the messages defined in
+ * include/ui/Camera.h
+ */
+
+ /**
+ * Enable a message, or set of messages.
+ */
+ void enableMsgType(int32_t msgType)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->enable_msg_type)
+ mDevice->ops->enable_msg_type(mDevice, msgType);
+ }
+
+ /**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera hal
+ * should not rely on its client to call releaseRecordingFrame() to release
+ * video recording frames sent out by the cameral hal before and after the
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera hal clients must not
+ * modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+ void disableMsgType(int32_t msgType)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->disable_msg_type)
+ mDevice->ops->disable_msg_type(mDevice, msgType);
+ }
+
+ /**
+ * Query whether a message, or a set of messages, is enabled.
+ * Note that this is operates as an AND, if any of the messages
+ * queried are off, this will return false.
+ */
+ int msgTypeEnabled(int32_t msgType)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->msg_type_enabled)
+ return mDevice->ops->msg_type_enabled(mDevice, msgType);
+ return false;
+ }
+
+ /**
+ * Start preview mode.
+ */
+ status_t startPreview()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->start_preview)
+ return mDevice->ops->start_preview(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Stop a previously started preview.
+ */
+ void stopPreview()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->stop_preview)
+ mDevice->ops->stop_preview(mDevice);
+ }
+
+ /**
+ * Returns true if preview is enabled.
+ */
+ int previewEnabled()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->preview_enabled)
+ return mDevice->ops->preview_enabled(mDevice);
+ return false;
+ }
+
+ /**
+ * Request the camera hal to store meta data or real YUV data in
+ * the video buffers send out via CAMERA_MSG_VIDEO_FRRAME for a
+ * recording session. If it is not called, the default camera
+ * hal behavior is to store real YUV data in the video buffers.
+ *
+ * This method should be called before startRecording() in order
+ * to be effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the
+ * receiver of the video buffers to interpret the contents and
+ * to find the actual frame data with the help of the meta data
+ * in the buffer. How this is done is outside of the scope of
+ * this method.
+ *
+ * Some camera hal may not support storing meta data in the video
+ * buffers, but all camera hal should support storing real YUV data
+ * in the video buffers. If the camera hal does not support storing
+ * the meta data in the video buffers when it is requested to do
+ * do, INVALID_OPERATION must be returned. It is very useful for
+ * the camera hal to pass meta data rather than the actual frame
+ * data directly to the video encoder, since the amount of the
+ * uncompressed frame data can be very large if video size is large.
+ *
+ * @param enable if true to instruct the camera hal to store
+ * meta data in the video buffers; false to instruct
+ * the camera hal to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+
+ status_t storeMetaDataInBuffers(int enable)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->store_meta_data_in_buffers)
+ return mDevice->ops->store_meta_data_in_buffers(mDevice, enable);
+ return enable ? INVALID_OPERATION: OK;
+ }
+
+ /**
+ * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME
+ * message is sent with the corresponding frame. Every record frame must be released
+ * by a cameral hal client via releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's responsibility
+ * to manage the life-cycle of the video recording frames, and the client must
+ * not modify/access any video recording frames.
+ */
+ status_t startRecording()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->start_recording)
+ return mDevice->ops->start_recording(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Stop a previously started recording.
+ */
+ void stopRecording()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->stop_recording)
+ mDevice->ops->stop_recording(mDevice);
+ }
+
+ /**
+ * Returns true if recording is enabled.
+ */
+ int recordingEnabled()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->recording_enabled)
+ return mDevice->ops->recording_enabled(mDevice);
+ return false;
+ }
+
+ /**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera hal client's responsibility to release video recording
+ * frames sent out by the camera hal before the camera hal receives
+ * a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives
+ * the call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's
+ * responsibility of managing the life-cycle of the video recording
+ * frames.
+ */
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->release_recording_frame) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+ void *data = ((uint8_t *)heap->base()) + offset;
+ return mDevice->ops->release_recording_frame(mDevice, data);
+ }
+ }
+
+ /**
+ * Start auto focus, the notification callback routine is called
+ * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus()
+ * will be called again if another auto focus is needed.
+ */
+ status_t autoFocus()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->auto_focus)
+ return mDevice->ops->auto_focus(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress
+ * or not, this function will return the focus position to the default.
+ * If the camera does not support auto-focus, this is a no-op.
+ */
+ status_t cancelAutoFocus()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->cancel_auto_focus)
+ return mDevice->ops->cancel_auto_focus(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Take a picture.
+ */
+ status_t takePicture()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->take_picture)
+ return mDevice->ops->take_picture(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Cancel a picture that was started with takePicture. Calling this
+ * method when no picture is being taken is a no-op.
+ */
+ status_t cancelPicture()
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->cancel_picture)
+ return mDevice->ops->cancel_picture(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported. */
+ status_t setParameters(const CameraParameters &params)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->set_parameters)
+ return mDevice->ops->set_parameters(mDevice,
+ params.flatten().string());
+ return INVALID_OPERATION;
+ }
+
+ /** Return the camera parameters. */
+ CameraParameters getParameters() const
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ CameraParameters parms;
+ if (mDevice->ops->get_parameters) {
+ char *temp = mDevice->ops->get_parameters(mDevice);
+ String8 str_parms(temp);
+ free(temp);
+ parms.unflatten(str_parms);
+ }
+ return parms;
+ }
+
+ /**
+ * Send command to camera driver.
+ */
+ status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->send_command)
+ return mDevice->ops->send_command(mDevice, cmd, arg1, arg2);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+ void release() {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->release)
+ mDevice->ops->release(mDevice);
+ }
+
+ /**
+ * Dump state of the camera hardware
+ */
+ status_t dump(int fd, const Vector<String16>& args) const
+ {
+ LOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->dump)
+ return mDevice->ops->dump(mDevice, fd);
+ return OK; // It's fine if the HAL doesn't implement dump()
+ }
+
+private:
+ camera_device_t *mDevice;
+ String8 mName;
+
+ static void __notify_cb(int32_t msg_type, int32_t ext1,
+ int32_t ext2, void *user)
+ {
+ LOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ __this->mNotifyCb(msg_type, ext1, ext2, __this->mCbUser);
+ }
+
+ static void __data_cb(int32_t msg_type,
+ const camera_memory_t *data,
+ void *user)
+ {
+ LOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+ __this->mDataCb(msg_type, mem, __this->mCbUser);
+ }
+
+ static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
+ const camera_memory_t *data,
+ void *user)
+ {
+ LOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ // Start refcounting the heap object from here on. When the clients
+ // drop all references, it will be destroyed (as well as the enclosed
+ // MemoryHeapBase.
+ sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+ __this->mDataCbTimestamp(timestamp, msg_type, mem, __this->mCbUser);
+ }
+
+ // This is a utility class that combines a MemoryHeapBase and a MemoryBase
+ // in one. Since we tend to use them in a one-to-one relationship, this is
+ // handy.
+
+ class CameraHeapMemory : public MemoryBase {
+ public:
+ CameraHeapMemory(size_t size) :
+ MemoryBase(new MemoryHeapBase(size), 0, size)
+ {
+ handle.data = getHeap()->base();
+ handle.size = size;
+ handle.handle = this;
+ }
+
+ camera_memory_t handle;
+ };
+
+ static camera_memory_t* __get_memory(size_t size,
+ void *user __attribute__((unused)))
+ {
+ // We allocate the object here, but we do not assign it to a strong
+ // pointer yet. The HAL will pass it back to us via the data callback
+ // or the data-timestamp callback, and from there on we will wrap it
+ // within a strong pointer.
+
+ CameraHeapMemory *mem = new CameraHeapMemory(size);
+ return &mem->handle;
+ }
+
+ static ANativeWindow *__to_anw(void *user)
+ {
+ CameraHardwareInterface *__this =
+ reinterpret_cast<CameraHardwareInterface *>(user);
+ return __this->mPreviewWindow.get();
+ }
+#define anw(n) __to_anw(((struct camera_preview_window *)n)->user)
+
+ static int __dequeue_buffer(struct preview_stream_ops* w,
+ buffer_handle_t** buffer)
+ {
+ int rc;
+ ANativeWindow *a = anw(w);
+ ANativeWindowBuffer* anb;
+ rc = a->dequeueBuffer(a, &anb);
+ if (!rc) {
+ rc = a->lockBuffer(a, anb);
+ if (!rc)
+ *buffer = &anb->handle;
+ else
+ a->cancelBuffer(a, anb);
+ }
+ return rc;
+ }
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
+#endif
+
+ static int __enqueue_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->queueBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
+ static int __cancel_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->cancelBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
+ static int __set_buffer_count(struct preview_stream_ops* w, int count)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_buffer_count(a, count);
+ }
+
+ static int __set_buffers_geometry(struct preview_stream_ops* w,
+ int width, int height, int format)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_buffers_geometry(a,
+ width, height, format);
+ }
+
+ static int __set_crop(struct preview_stream_ops *w,
+ int left, int top, int right, int bottom)
+ {
+ ANativeWindow *a = anw(w);
+ android_native_rect_t crop;
+ crop.left = left;
+ crop.top = top;
+ crop.right = right;
+ crop.bottom = bottom;
+ return native_window_set_crop(a, &crop);
+ }
+
+ static int __set_usage(struct preview_stream_ops* w, int usage)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_usage(a, usage);
+ }
+
+ static int __set_swap_interval(struct preview_stream_ops *w, int interval)
+ {
+ ANativeWindow *a = anw(w);
+ return a->setSwapInterval(a, interval);
+ }
+
+ static int __get_min_undequeued_buffer_count(
+ const struct preview_stream_ops *w,
+ int *count)
+ {
+ ANativeWindow *a = anw(w);
+ return a->query(a, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, count);
+ }
+
+ void initHalPreviewWindow()
+ {
+ mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+ mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
+ mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
+ mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
+ mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
+ mHalPreviewWindow.nw.set_crop = __set_crop;
+ mHalPreviewWindow.nw.set_usage = __set_usage;
+ mHalPreviewWindow.nw.set_swap_interval = __set_swap_interval;
+
+ mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
+ __get_min_undequeued_buffer_count;
+ }
+
+ sp<ANativeWindow> mPreviewWindow;
+
+ struct camera_preview_window {
+ struct preview_stream_ops nw;
+ void *user;
+ };
+
+ struct camera_preview_window mHalPreviewWindow;
+
+ notify_callback mNotifyCb;
+ data_callback mDataCb;
+ data_callback_timestamp mDataCbTimestamp;
+ void *mCbUser;
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a09e16b..1e8c30b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -16,6 +16,7 @@
*/
#define LOG_TAG "CameraService"
+//#define LOG_NDEBUG 0
#include <stdio.h>
#include <sys/types.h>
@@ -37,6 +38,7 @@
#include <utils/String16.h>
#include "CameraService.h"
+#include "CameraHardwareInterface.h"
namespace android {
@@ -69,22 +71,32 @@ static int getCallingUid() {
static CameraService *gCameraService;
CameraService::CameraService()
-:mSoundRef(0)
+:mSoundRef(0), mModule(0)
{
LOGI("CameraService started (pid=%d)", getpid());
+ gCameraService = this;
+}
- mNumberOfCameras = HAL_getNumberOfCameras();
- if (mNumberOfCameras > MAX_CAMERAS) {
- LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
- mNumberOfCameras, MAX_CAMERAS);
- mNumberOfCameras = MAX_CAMERAS;
- }
-
- for (int i = 0; i < mNumberOfCameras; i++) {
- setCameraFree(i);
+void CameraService::onFirstRef()
+{
+ BnCameraService::onFirstRef();
+
+ if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&mModule) < 0) {
+ LOGE("Could not load camera HAL module");
+ mNumberOfCameras = 0;
+ }
+ else {
+ mNumberOfCameras = mModule->get_number_of_cameras();
+ if (mNumberOfCameras > MAX_CAMERAS) {
+ LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
+ mNumberOfCameras, MAX_CAMERAS);
+ mNumberOfCameras = MAX_CAMERAS;
+ }
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ setCameraFree(i);
+ }
}
-
- gCameraService = this;
}
CameraService::~CameraService() {
@@ -103,12 +115,19 @@ int32_t CameraService::getNumberOfCameras() {
status_t CameraService::getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo) {
+ if (!mModule) {
+ return NO_INIT;
+ }
+
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
return BAD_VALUE;
}
- HAL_getCameraInfo(cameraId, cameraInfo);
- return OK;
+ struct camera_info info;
+ status_t rc = mModule->get_camera_info(cameraId, &info);
+ cameraInfo->facing = info.facing;
+ cameraInfo->orientation = info.orientation;
+ return rc;
}
sp<ICamera> CameraService::connect(
@@ -116,6 +135,11 @@ sp<ICamera> CameraService::connect(
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
+ if (!mModule) {
+ LOGE("Camera HAL module not loaded");
+ return NULL;
+ }
+
sp<Client> client;
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
@@ -146,15 +170,19 @@ sp<ICamera> CameraService::connect(
return NULL;
}
- sp<CameraHardwareInterface> hardware = HAL_openCameraHardware(cameraId);
- if (hardware == NULL) {
- LOGE("Fail to open camera hardware (id=%d)", cameraId);
+ struct camera_info info;
+ if (mModule->get_camera_info(cameraId, &info) != OK) {
+ LOGE("Invalid camera id %d", cameraId);
return NULL;
}
- CameraInfo info;
- HAL_getCameraInfo(cameraId, &info);
- client = new Client(this, cameraClient, hardware, cameraId, info.facing,
- callingPid);
+
+ char camera_device_name[10];
+ snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
+
+ client = new Client(this, cameraClient,
+ new CameraHardwareInterface(&mModule->common,
+ camera_device_name),
+ cameraId, info.facing, callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
@@ -244,7 +272,7 @@ void CameraService::setCameraFree(int cameraId) {
static MediaPlayer* newMediaPlayer(const char *file) {
MediaPlayer* mp = new MediaPlayer();
if (mp->setDataSource(file, NULL) == NO_ERROR) {
- mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
+ mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
mp->prepare();
} else {
LOGE("Failed to load CameraService sounds: %s", file);
@@ -283,7 +311,7 @@ void CameraService::playSound(sound_kind kind) {
// do not play the sound if stream volume is 0
// (typically because ringer mode is silent).
int index;
- AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+ AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, &index);
if (index != 0) {
player->seekTo(0);
player->start();
@@ -320,7 +348,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
CAMERA_MSG_FOCUS);
// Callback is disabled by default
- mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mPlayShutterSound = true;
cameraService->setCameraBusy(cameraId);
@@ -410,7 +438,7 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
return NO_ERROR;
}
- mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mClientPid = callingPid;
mCameraClient = client;
@@ -472,15 +500,15 @@ status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
result = NO_ERROR;
// return if no change in surface.
- // asBinder() is safe on NULL (returns NULL)
- if (getISurface(surface)->asBinder() == mSurface) {
+ sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
+ if (binder == mSurface) {
return result;
}
if (mSurface != 0) {
LOG1("clearing old preview surface %p", mSurface.get());
}
- mSurface = getISurface(surface)->asBinder();
+ mSurface = binder;
mPreviewWindow = surface;
// If preview has been already started, register preview
@@ -543,7 +571,7 @@ void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
if (checkPidAndHardware() != NO_ERROR) return;
mPreviewCallbackFlag = callback_flag;
- if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+ if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
} else {
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
@@ -666,20 +694,6 @@ void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
mHardware->releaseRecordingFrame(mem);
}
-int32_t CameraService::Client::getNumberOfVideoBuffers() const {
- LOG1("getNumberOfVideoBuffers");
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return 0;
- return mHardware->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> CameraService::Client::getVideoBuffer(int32_t index) const {
- LOG1("getVideoBuffer: %d", index);
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return 0;
- return mHardware->getVideoBuffer(index);
-}
-
status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
{
LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -938,7 +952,7 @@ void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
switch (msgType) {
case CAMERA_MSG_SHUTTER:
// ext1 is the dimension of the yuv picture.
- client->handleShutter((image_rect_type *)ext1);
+ client->handleShutter();
break;
default:
client->handleGenericNotify(msgType, ext1, ext2);
@@ -997,9 +1011,7 @@ void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
}
// snapshot taken callback
-// "size" is the width and height of yuv picture for registerBuffer.
-// If it is NULL, use the picture size from parameters.
-void CameraService::Client::handleShutter(image_rect_type *size) {
+void CameraService::Client::handleShutter(void) {
if (mPlayShutterSound) {
mCameraService->playSound(SOUND_SHUTTER);
}
@@ -1025,7 +1037,7 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
int flags = mPreviewCallbackFlag;
// is callback enabled?
- if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+ if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
// If the enable bit is off, the copy-out and one-shot bits are ignored
LOG2("frame callback is disabled");
mLock.unlock();
@@ -1036,17 +1048,17 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
sp<ICameraClient> c = mCameraClient;
// clear callback flags if no client or one-shot mode
- if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+ if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
LOG2("Disable preview callback");
- mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
- FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
- FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+ CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+ CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
if (c != 0) {
// Is the received frame copied out or not?
- if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+ if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
LOG2("frame is copied");
copyFrameAndPostCopiedFrame(c, heap, offset, size);
} else {
@@ -1257,12 +1269,4 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
return NO_ERROR;
}
-sp<ISurface> CameraService::getISurface(const sp<Surface>& surface) {
- if (surface != 0) {
- return surface->getISurface();
- } else {
- return sp<ISurface>(0);
- }
-}
-
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1c43b00..5e2d571 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -19,9 +19,8 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <binder/BinderService.h>
-
#include <camera/ICameraService.h>
-#include <camera/CameraHardwareInterface.h>
+#include <hardware/camera.h>
/* This needs to be increased if we can have more cameras */
#define MAX_CAMERAS 2
@@ -30,6 +29,7 @@ namespace android {
class MemoryHeapBase;
class MediaPlayer;
+class CameraHardwareInterface;
class CameraService :
public BinderService<CameraService>,
@@ -53,6 +53,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
+ virtual void onFirstRef();
enum sound_kind {
SOUND_SHUTTER = 0,
@@ -79,12 +80,6 @@ private:
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
int mSoundRef; // reference count (release all MediaPlayer when 0)
- // Used by Client objects to extract the ISurface from a Surface object.
- // This is used because making Client a friend class of Surface would
- // require including this header in Surface.h since Client is a nested
- // class.
- static sp<ISurface> getISurface(const sp<Surface>& surface);
-
class Client : public BnCamera
{
public:
@@ -99,8 +94,6 @@ private:
virtual status_t startPreview();
virtual void stopPreview();
virtual bool previewEnabled();
- virtual int32_t getNumberOfVideoBuffers() const;
- virtual sp<IMemory> getVideoBuffer(int32_t index) const;
virtual status_t storeMetaDataInBuffers(bool enabled);
virtual status_t startRecording();
virtual void stopRecording();
@@ -152,7 +145,7 @@ private:
// convert client from cookie
static sp<Client> getClientFromCookie(void* user);
// handlers for messages
- void handleShutter(image_rect_type *size);
+ void handleShutter(void);
void handlePreviewData(const sp<IMemory>& mem);
void handlePostview(const sp<IMemory>& mem);
void handleRawPicture(const sp<IMemory>& mem);
@@ -207,6 +200,8 @@ private:
// is found to be disabled. It returns true if mLock is grabbed.
bool lockIfMessageWanted(int32_t msgType);
};
+
+ camera_module_t *mModule;
};
} // namespace android
diff --git a/services/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
index cf4e42f..cf7302a 100644
--- a/services/camera/tests/CameraServiceTest/Android.mk
+++ b/services/camera/tests/CameraServiceTest/Android.mk
@@ -19,7 +19,7 @@ LOCAL_SHARED_LIBRARIES += \
libutils \
libui \
libcamera_client \
- libsurfaceflinger_client
+ libgui
# Disable it because the ISurface interface may change, and before we have a
# chance to fix this test, we don't want to break normal builds.
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index 8a228fd..f86ca47 100644
--- a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -830,10 +830,10 @@ public:
ASSERT(c->previewEnabled() == true);
sleep(2);
c->stopPreview();
- if ((v & FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
+ if ((v & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
} else {
- if ((v & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
+ if ((v & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
} else {
cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
@@ -849,7 +849,7 @@ public:
ASSERT(c->recordingEnabled() == false);
sp<MSurface> surface = new MSurface();
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
- c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
cc->setReleaser(c.get());
c->startRecording();
ASSERT(c->recordingEnabled() == true);
@@ -870,7 +870,7 @@ public:
CameraParameters param(c->getParameters());
param.setPreviewSize(w, h);
- c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
c->setParameters(param.flatten());
c->startPreview();