am 4055b780: Merge "move native services under services/" into gingerbread
Merge commit '4055b780bb7e85abcf4754b84e50bf407c45bec8' into gingerbread-plus-aosp * commit '4055b780bb7e85abcf4754b84e50bf407c45bec8': move native services under services/
This commit is contained in:
commit
76648df37d
@ -1,66 +0,0 @@
|
||||
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
|
||||
#
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
CameraService.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES:= \
|
||||
libui \
|
||||
libutils \
|
||||
libbinder \
|
||||
libcutils \
|
||||
libmedia \
|
||||
libcamera_client \
|
||||
libsurfaceflinger_client
|
||||
|
||||
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)
|
@ -1,410 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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 "CameraHardwareStub"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "CameraHardwareStub.h"
|
||||
#include <utils/threads.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "CannedJpeg.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
CameraHardwareStub::CameraHardwareStub()
|
||||
: mParameters(),
|
||||
mPreviewHeap(0),
|
||||
mRawHeap(0),
|
||||
mFakeCamera(0),
|
||||
mPreviewFrameSize(0),
|
||||
mNotifyCb(0),
|
||||
mDataCb(0),
|
||||
mDataCbTimestamp(0),
|
||||
mCallbackCookie(0),
|
||||
mMsgEnabled(0),
|
||||
mCurrentPreviewFrame(0)
|
||||
{
|
||||
initDefaultParameters();
|
||||
}
|
||||
|
||||
void CameraHardwareStub::initDefaultParameters()
|
||||
{
|
||||
CameraParameters p;
|
||||
|
||||
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
|
||||
p.setPreviewSize(320, 240);
|
||||
p.setPreviewFrameRate(15);
|
||||
p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
|
||||
|
||||
p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
|
||||
p.setPictureSize(320, 240);
|
||||
p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
|
||||
|
||||
if (setParameters(p) != NO_ERROR) {
|
||||
LOGE("Failed to set default parameters?!");
|
||||
}
|
||||
}
|
||||
|
||||
void CameraHardwareStub::initHeapLocked()
|
||||
{
|
||||
// Create raw heap.
|
||||
int picture_width, picture_height;
|
||||
mParameters.getPictureSize(&picture_width, &picture_height);
|
||||
mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
|
||||
|
||||
int preview_width, preview_height;
|
||||
mParameters.getPreviewSize(&preview_width, &preview_height);
|
||||
LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
|
||||
|
||||
// Note that we enforce yuv420sp in setParameters().
|
||||
int how_big = preview_width * preview_height * 3 / 2;
|
||||
|
||||
// If we are being reinitialized to the same size as before, no
|
||||
// work needs to be done.
|
||||
if (how_big == mPreviewFrameSize)
|
||||
return;
|
||||
|
||||
mPreviewFrameSize = how_big;
|
||||
|
||||
// Make a new mmap'ed heap that can be shared across processes.
|
||||
// use code below to test with pmem
|
||||
mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
|
||||
// Make an IMemory for each frame so that we can reuse them in callbacks.
|
||||
for (int i = 0; i < kBufferCount; i++) {
|
||||
mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
|
||||
}
|
||||
|
||||
// Recreate the fake camera to reflect the current size.
|
||||
delete mFakeCamera;
|
||||
mFakeCamera = new FakeCamera(preview_width, preview_height);
|
||||
}
|
||||
|
||||
CameraHardwareStub::~CameraHardwareStub()
|
||||
{
|
||||
delete mFakeCamera;
|
||||
mFakeCamera = 0; // paranoia
|
||||
}
|
||||
|
||||
sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
|
||||
{
|
||||
return mPreviewHeap;
|
||||
}
|
||||
|
||||
sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
|
||||
{
|
||||
return mRawHeap;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
|
||||
data_callback data_cb,
|
||||
data_callback_timestamp data_cb_timestamp,
|
||||
void* user)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
mNotifyCb = notify_cb;
|
||||
mDataCb = data_cb;
|
||||
mDataCbTimestamp = data_cb_timestamp;
|
||||
mCallbackCookie = user;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::enableMsgType(int32_t msgType)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
mMsgEnabled |= msgType;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::disableMsgType(int32_t msgType)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
mMsgEnabled &= ~msgType;
|
||||
}
|
||||
|
||||
bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
return (mMsgEnabled & msgType);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int CameraHardwareStub::previewThread()
|
||||
{
|
||||
mLock.lock();
|
||||
// the attributes below can change under our feet...
|
||||
|
||||
int previewFrameRate = mParameters.getPreviewFrameRate();
|
||||
|
||||
// Find the offset within the heap of the current buffer.
|
||||
ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
|
||||
|
||||
sp<MemoryHeapBase> heap = mPreviewHeap;
|
||||
|
||||
// this assumes the internal state of fake camera doesn't change
|
||||
// (or is thread safe)
|
||||
FakeCamera* fakeCamera = mFakeCamera;
|
||||
|
||||
sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
|
||||
|
||||
mLock.unlock();
|
||||
|
||||
// TODO: here check all the conditions that could go wrong
|
||||
if (buffer != 0) {
|
||||
// Calculate how long to wait between frames.
|
||||
int delay = (int)(1000000.0f / float(previewFrameRate));
|
||||
|
||||
// This is always valid, even if the client died -- the memory
|
||||
// is still mapped in our process.
|
||||
void *base = heap->base();
|
||||
|
||||
// Fill the current frame with the fake camera.
|
||||
uint8_t *frame = ((uint8_t *)base) + offset;
|
||||
fakeCamera->getNextFrameAsYuv420(frame);
|
||||
|
||||
//LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
|
||||
|
||||
// Notify the client of a new frame.
|
||||
if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
|
||||
mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
|
||||
|
||||
// Advance the buffer pointer.
|
||||
mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
|
||||
|
||||
// Wait for it...
|
||||
usleep(delay);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::startPreview()
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (mPreviewThread != 0) {
|
||||
// already running
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
mPreviewThread = new PreviewThread(this);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::stopPreview()
|
||||
{
|
||||
sp<PreviewThread> previewThread;
|
||||
|
||||
{ // scope for the lock
|
||||
Mutex::Autolock lock(mLock);
|
||||
previewThread = mPreviewThread;
|
||||
}
|
||||
|
||||
// don't hold the lock while waiting for the thread to quit
|
||||
if (previewThread != 0) {
|
||||
previewThread->requestExitAndWait();
|
||||
}
|
||||
|
||||
Mutex::Autolock lock(mLock);
|
||||
mPreviewThread.clear();
|
||||
}
|
||||
|
||||
bool CameraHardwareStub::previewEnabled() {
|
||||
return mPreviewThread != 0;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::startRecording()
|
||||
{
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::stopRecording()
|
||||
{
|
||||
}
|
||||
|
||||
bool CameraHardwareStub::recordingEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
|
||||
{
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int CameraHardwareStub::beginAutoFocusThread(void *cookie)
|
||||
{
|
||||
CameraHardwareStub *c = (CameraHardwareStub *)cookie;
|
||||
return c->autoFocusThread();
|
||||
}
|
||||
|
||||
int CameraHardwareStub::autoFocusThread()
|
||||
{
|
||||
if (mMsgEnabled & CAMERA_MSG_FOCUS)
|
||||
mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::autoFocus()
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (createThread(beginAutoFocusThread, this) == false)
|
||||
return UNKNOWN_ERROR;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::cancelAutoFocus()
|
||||
{
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
|
||||
{
|
||||
CameraHardwareStub *c = (CameraHardwareStub *)cookie;
|
||||
return c->pictureThread();
|
||||
}
|
||||
|
||||
int CameraHardwareStub::pictureThread()
|
||||
{
|
||||
if (mMsgEnabled & CAMERA_MSG_SHUTTER)
|
||||
mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
|
||||
|
||||
if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
|
||||
//FIXME: use a canned YUV image!
|
||||
// In the meantime just make another fake camera picture.
|
||||
int w, h;
|
||||
mParameters.getPictureSize(&w, &h);
|
||||
sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
|
||||
FakeCamera cam(w, h);
|
||||
cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
|
||||
mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
|
||||
}
|
||||
|
||||
if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
|
||||
sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
|
||||
sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
|
||||
memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
|
||||
mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::takePicture()
|
||||
{
|
||||
stopPreview();
|
||||
if (createThread(beginPictureThread, this) == false)
|
||||
return UNKNOWN_ERROR;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::cancelPicture()
|
||||
{
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
|
||||
{
|
||||
const size_t SIZE = 256;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
AutoMutex lock(&mLock);
|
||||
if (mFakeCamera != 0) {
|
||||
mFakeCamera->dump(fd);
|
||||
mParameters.dump(fd, args);
|
||||
snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
|
||||
result.append(buffer);
|
||||
} else {
|
||||
result.append("No camera client yet.\n");
|
||||
}
|
||||
write(fd, result.string(), result.size());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::setParameters(const CameraParameters& params)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
// XXX verify params
|
||||
|
||||
if (strcmp(params.getPreviewFormat(),
|
||||
CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
|
||||
LOGE("Only yuv420sp preview is supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(params.getPictureFormat(),
|
||||
CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
|
||||
LOGE("Only jpeg still pictures are supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int w, h;
|
||||
params.getPictureSize(&w, &h);
|
||||
if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
|
||||
LOGE("Still picture size must be size of canned JPEG (%dx%d)",
|
||||
kCannedJpegWidth, kCannedJpegHeight);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mParameters = params;
|
||||
initHeapLocked();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CameraParameters CameraHardwareStub::getParameters() const
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
return mParameters;
|
||||
}
|
||||
|
||||
status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
|
||||
int32_t arg2)
|
||||
{
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
void CameraHardwareStub::release()
|
||||
{
|
||||
}
|
||||
|
||||
sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
|
||||
{
|
||||
return new CameraHardwareStub();
|
||||
}
|
||||
|
||||
static CameraInfo sCameraInfo[] = {
|
||||
{
|
||||
CAMERA_FACING_BACK,
|
||||
90, /* orientation */
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int HAL_getNumberOfCameras()
|
||||
{
|
||||
return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
|
||||
}
|
||||
|
||||
extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
|
||||
{
|
||||
memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
|
||||
}
|
||||
|
||||
extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
|
||||
{
|
||||
return CameraHardwareStub::createInstance();
|
||||
}
|
||||
|
||||
}; // namespace android
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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_HARDWARE_CAMERA_HARDWARE_STUB_H
|
||||
#define ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
|
||||
|
||||
#include "FakeCamera.h"
|
||||
#include <utils/threads.h>
|
||||
#include <camera/CameraHardwareInterface.h>
|
||||
#include <binder/MemoryBase.h>
|
||||
#include <binder/MemoryHeapBase.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class CameraHardwareStub : public CameraHardwareInterface {
|
||||
public:
|
||||
virtual sp<IMemoryHeap> getPreviewHeap() const;
|
||||
virtual sp<IMemoryHeap> getRawHeap() const;
|
||||
|
||||
virtual void setCallbacks(notify_callback notify_cb,
|
||||
data_callback data_cb,
|
||||
data_callback_timestamp data_cb_timestamp,
|
||||
void* user);
|
||||
|
||||
virtual void enableMsgType(int32_t msgType);
|
||||
virtual void disableMsgType(int32_t msgType);
|
||||
virtual bool msgTypeEnabled(int32_t msgType);
|
||||
|
||||
virtual status_t startPreview();
|
||||
virtual void stopPreview();
|
||||
virtual bool previewEnabled();
|
||||
|
||||
virtual status_t startRecording();
|
||||
virtual void stopRecording();
|
||||
virtual bool recordingEnabled();
|
||||
virtual void releaseRecordingFrame(const sp<IMemory>& mem);
|
||||
|
||||
virtual status_t autoFocus();
|
||||
virtual status_t cancelAutoFocus();
|
||||
virtual status_t takePicture();
|
||||
virtual status_t cancelPicture();
|
||||
virtual status_t dump(int fd, const Vector<String16>& args) const;
|
||||
virtual status_t setParameters(const CameraParameters& params);
|
||||
virtual CameraParameters getParameters() const;
|
||||
virtual status_t sendCommand(int32_t command, int32_t arg1,
|
||||
int32_t arg2);
|
||||
virtual void release();
|
||||
|
||||
static sp<CameraHardwareInterface> createInstance();
|
||||
|
||||
private:
|
||||
CameraHardwareStub();
|
||||
virtual ~CameraHardwareStub();
|
||||
|
||||
static const int kBufferCount = 4;
|
||||
|
||||
class PreviewThread : public Thread {
|
||||
CameraHardwareStub* mHardware;
|
||||
public:
|
||||
PreviewThread(CameraHardwareStub* hw) :
|
||||
#ifdef SINGLE_PROCESS
|
||||
// In single process mode this thread needs to be a java thread,
|
||||
// since we won't be calling through the binder.
|
||||
Thread(true),
|
||||
#else
|
||||
Thread(false),
|
||||
#endif
|
||||
mHardware(hw) { }
|
||||
virtual void onFirstRef() {
|
||||
run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
|
||||
}
|
||||
virtual bool threadLoop() {
|
||||
mHardware->previewThread();
|
||||
// loop until we need to quit
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void initDefaultParameters();
|
||||
void initHeapLocked();
|
||||
|
||||
int previewThread();
|
||||
|
||||
static int beginAutoFocusThread(void *cookie);
|
||||
int autoFocusThread();
|
||||
|
||||
static int beginPictureThread(void *cookie);
|
||||
int pictureThread();
|
||||
|
||||
mutable Mutex mLock;
|
||||
|
||||
CameraParameters mParameters;
|
||||
|
||||
sp<MemoryHeapBase> mPreviewHeap;
|
||||
sp<MemoryHeapBase> mRawHeap;
|
||||
sp<MemoryBase> mBuffers[kBufferCount];
|
||||
|
||||
FakeCamera *mFakeCamera;
|
||||
bool mPreviewRunning;
|
||||
int mPreviewFrameSize;
|
||||
|
||||
// protected by mLock
|
||||
sp<PreviewThread> mPreviewThread;
|
||||
|
||||
notify_callback mNotifyCb;
|
||||
data_callback mDataCb;
|
||||
data_callback_timestamp mDataCbTimestamp;
|
||||
void *mCallbackCookie;
|
||||
|
||||
int32_t mMsgEnabled;
|
||||
|
||||
// only used from PreviewThread
|
||||
int mCurrentPreviewFrame;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,194 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** Copyright (C) 2008, The Android Open Source Project
|
||||
** Copyright (C) 2008 HTC 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
|
||||
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
|
||||
|
||||
#include <camera/ICameraService.h>
|
||||
#include <camera/CameraHardwareInterface.h>
|
||||
|
||||
/* This needs to be increased if we can have more cameras */
|
||||
#define MAX_CAMERAS 2
|
||||
|
||||
namespace android {
|
||||
|
||||
class MemoryHeapBase;
|
||||
class MediaPlayer;
|
||||
|
||||
class CameraService: public BnCameraService
|
||||
{
|
||||
class Client;
|
||||
public:
|
||||
static void instantiate();
|
||||
|
||||
CameraService();
|
||||
virtual ~CameraService();
|
||||
|
||||
virtual int32_t getNumberOfCameras();
|
||||
virtual status_t getCameraInfo(int cameraId,
|
||||
struct CameraInfo* cameraInfo);
|
||||
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
|
||||
virtual void removeClient(const sp<ICameraClient>& cameraClient);
|
||||
virtual sp<Client> getClientById(int cameraId);
|
||||
|
||||
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);
|
||||
|
||||
enum sound_kind {
|
||||
SOUND_SHUTTER = 0,
|
||||
SOUND_RECORDING = 1,
|
||||
NUM_SOUNDS
|
||||
};
|
||||
|
||||
void loadSound();
|
||||
void playSound(sound_kind kind);
|
||||
void releaseSound();
|
||||
|
||||
private:
|
||||
Mutex mServiceLock;
|
||||
wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock
|
||||
int mNumberOfCameras;
|
||||
|
||||
// atomics to record whether the hardware is allocated to some client.
|
||||
volatile int32_t mBusy[MAX_CAMERAS];
|
||||
void setCameraBusy(int cameraId);
|
||||
void setCameraFree(int cameraId);
|
||||
|
||||
// sounds
|
||||
Mutex mSoundLock;
|
||||
sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
|
||||
int mSoundRef; // reference count (release all MediaPlayer when 0)
|
||||
|
||||
class Client : public BnCamera
|
||||
{
|
||||
public:
|
||||
// ICamera interface (see ICamera for details)
|
||||
virtual void disconnect();
|
||||
virtual status_t connect(const sp<ICameraClient>& client);
|
||||
virtual status_t lock();
|
||||
virtual status_t unlock();
|
||||
virtual status_t setPreviewDisplay(const sp<ISurface>& surface);
|
||||
virtual void setPreviewCallbackFlag(int flag);
|
||||
virtual status_t startPreview();
|
||||
virtual void stopPreview();
|
||||
virtual bool previewEnabled();
|
||||
virtual status_t startRecording();
|
||||
virtual void stopRecording();
|
||||
virtual bool recordingEnabled();
|
||||
virtual void releaseRecordingFrame(const sp<IMemory>& mem);
|
||||
virtual status_t autoFocus();
|
||||
virtual status_t cancelAutoFocus();
|
||||
virtual status_t takePicture();
|
||||
virtual status_t setParameters(const String8& params);
|
||||
virtual String8 getParameters() const;
|
||||
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
|
||||
private:
|
||||
friend class CameraService;
|
||||
Client(const sp<CameraService>& cameraService,
|
||||
const sp<ICameraClient>& cameraClient,
|
||||
int cameraId,
|
||||
int clientPid);
|
||||
~Client();
|
||||
|
||||
// return our camera client
|
||||
const sp<ICameraClient>& getCameraClient() { return mCameraClient; }
|
||||
|
||||
// check whether the calling process matches mClientPid.
|
||||
status_t checkPid() const;
|
||||
status_t checkPidAndHardware() const; // also check mHardware != 0
|
||||
|
||||
// these are internal functions used to set up preview buffers
|
||||
status_t registerPreviewBuffers();
|
||||
status_t setOverlay();
|
||||
|
||||
// camera operation mode
|
||||
enum camera_mode {
|
||||
CAMERA_PREVIEW_MODE = 0, // frame automatically released
|
||||
CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame()
|
||||
};
|
||||
// these are internal functions used for preview/recording
|
||||
status_t startCameraMode(camera_mode mode);
|
||||
status_t startPreviewMode();
|
||||
status_t startRecordingMode();
|
||||
|
||||
// these are static callback functions
|
||||
static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
|
||||
static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
|
||||
static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
|
||||
// convert client from cookie
|
||||
static sp<Client> getClientFromCookie(void* user);
|
||||
// handlers for messages
|
||||
void handleShutter(image_rect_type *size);
|
||||
void handlePreviewData(const sp<IMemory>& mem);
|
||||
void handlePostview(const sp<IMemory>& mem);
|
||||
void handleRawPicture(const sp<IMemory>& mem);
|
||||
void handleCompressedPicture(const sp<IMemory>& mem);
|
||||
void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
|
||||
void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr);
|
||||
void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
|
||||
|
||||
void copyFrameAndPostCopiedFrame(
|
||||
const sp<ICameraClient>& client,
|
||||
const sp<IMemoryHeap>& heap,
|
||||
size_t offset, size_t size);
|
||||
|
||||
// these are initialized in the constructor.
|
||||
sp<CameraService> mCameraService; // immutable after constructor
|
||||
sp<ICameraClient> mCameraClient;
|
||||
int mCameraId; // immutable after constructor
|
||||
pid_t mClientPid;
|
||||
sp<CameraHardwareInterface> mHardware; // cleared after disconnect()
|
||||
bool mUseOverlay; // immutable after constructor
|
||||
sp<OverlayRef> mOverlayRef;
|
||||
int mOverlayW;
|
||||
int mOverlayH;
|
||||
int mPreviewCallbackFlag;
|
||||
int mOrientation;
|
||||
|
||||
// Ensures atomicity among the public methods
|
||||
mutable Mutex mLock;
|
||||
sp<ISurface> mSurface;
|
||||
|
||||
// If the user want us to return a copy of the preview frame (instead
|
||||
// of the original one), we allocate mPreviewBuffer and reuse it if possible.
|
||||
sp<MemoryHeapBase> mPreviewBuffer;
|
||||
|
||||
// We need to avoid the deadlock when the incoming command thread and
|
||||
// the CameraHardwareInterface callback thread both want to grab mLock.
|
||||
// An extra flag is used to tell the callback thread that it should stop
|
||||
// trying to deliver the callback messages if the client is not
|
||||
// interested in it anymore. For example, if the client is calling
|
||||
// stopPreview(), the preview frame messages do not need to be delivered
|
||||
// anymore.
|
||||
|
||||
// This function takes the same parameter as the enableMsgType() and
|
||||
// disableMsgType() functions in CameraHardwareInterface.
|
||||
void enableMsgType(int32_t msgType);
|
||||
void disableMsgType(int32_t msgType);
|
||||
volatile int32_t mMsgEnabled;
|
||||
|
||||
// This function keeps trying to grab mLock, or give up if the message
|
||||
// is found to be disabled. It returns true if mLock is grabbed.
|
||||
bool lockIfMessageWanted(int32_t msgType);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif
|
@ -1,734 +0,0 @@
|
||||
const int kCannedJpegWidth = 320;
|
||||
const int kCannedJpegHeight = 240;
|
||||
const int kCannedJpegSize = 8733;
|
||||
|
||||
const char kCannedJpeg[] = {
|
||||
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
|
||||
0x01, 0x01, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0xff, 0xe1, 0x00, 0x66,
|
||||
0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x1a, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x3e, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x46, 0x00, 0x00, 0x00, 0x28, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x31, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x50, 0x61, 0x69, 0x6e, 0x74, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x76, 0x33,
|
||||
0x2e, 0x33, 0x36, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02,
|
||||
0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05,
|
||||
0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, 0x07, 0x06, 0x08, 0x0c,
|
||||
0x0a, 0x0c, 0x0c, 0x0b, 0x0a, 0x0b, 0x0b, 0x0d, 0x0e, 0x12, 0x10, 0x0d,
|
||||
0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, 0x16, 0x10, 0x11, 0x13, 0x14, 0x15,
|
||||
0x15, 0x15, 0x0c, 0x0f, 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15,
|
||||
0x14, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05,
|
||||
0x09, 0x05, 0x05, 0x09, 0x14, 0x0d, 0x0b, 0x0d, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0,
|
||||
0x00, 0x11, 0x08, 0x00, 0xf0, 0x01, 0x40, 0x03, 0x01, 0x22, 0x00, 0x02,
|
||||
0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01,
|
||||
0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
|
||||
0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01,
|
||||
0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
|
||||
0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
|
||||
0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
|
||||
0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
|
||||
0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
|
||||
0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
|
||||
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
|
||||
0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
|
||||
0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
|
||||
0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
|
||||
0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
|
||||
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
|
||||
0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
|
||||
0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00,
|
||||
0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
|
||||
0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1,
|
||||
0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a,
|
||||
0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
|
||||
0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75,
|
||||
0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
|
||||
0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
|
||||
0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5,
|
||||
0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
|
||||
0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2,
|
||||
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5,
|
||||
0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00,
|
||||
0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, 0xd2, 0xa3, 0x95, 0xbb,
|
||||
0x54, 0x84, 0xe0, 0x66, 0xa0, 0x27, 0x27, 0x35, 0xed, 0x9e, 0x50, 0x95,
|
||||
0x2c, 0x4b, 0xc6, 0x6a, 0x35, 0x1b, 0x8e, 0x2a, 0x70, 0x30, 0x28, 0x00,
|
||||
0xa8, 0xe5, 0x6e, 0x71, 0x52, 0x31, 0xda, 0x33, 0x50, 0x13, 0x93, 0x40,
|
||||
0x09, 0x52, 0xc6, 0xb8, 0x19, 0xf5, 0xa6, 0x2a, 0xee, 0x6c, 0x54, 0xd4,
|
||||
0x00, 0x54, 0x52, 0x36, 0x5b, 0x1e, 0x95, 0x23, 0xb6, 0xd5, 0xcd, 0x41,
|
||||
0x40, 0x05, 0x4c, 0x8b, 0xb5, 0x7d, 0xea, 0x34, 0x5d, 0xcd, 0xed, 0x53,
|
||||
0x50, 0x01, 0x50, 0xbb, 0x6e, 0x6f, 0x6a, 0x91, 0xdb, 0x6a, 0xfb, 0xd4,
|
||||
0x34, 0x00, 0x54, 0xe8, 0xbb, 0x57, 0x15, 0x1c, 0x6b, 0x96, 0xcf, 0xa5,
|
||||
0x4b, 0x40, 0x05, 0x42, 0xcd, 0xb9, 0xb3, 0x4f, 0x91, 0xb0, 0x31, 0xeb,
|
||||
0x51, 0x50, 0x02, 0x81, 0x93, 0x53, 0xa8, 0xda, 0x31, 0x51, 0xc4, 0xbc,
|
||||
0xe6, 0xa4, 0xa0, 0x00, 0x9c, 0x0a, 0x81, 0x8e, 0xe3, 0x9a, 0x92, 0x56,
|
||||
0xe3, 0x15, 0x15, 0x00, 0x28, 0x19, 0x38, 0xa9, 0xc0, 0xc0, 0xc5, 0x47,
|
||||
0x12, 0xf7, 0xa9, 0x28, 0x00, 0x27, 0x00, 0x9a, 0x80, 0x9c, 0x9c, 0xd3,
|
||||
0xe5, 0x6e, 0xd5, 0x1d, 0x00, 0x2a, 0x8d, 0xc7, 0x15, 0x3d, 0x32, 0x35,
|
||||
0xc0, 0xcf, 0xad, 0x3e, 0x80, 0x11, 0x8e, 0xd1, 0x9a, 0x82, 0x9f, 0x23,
|
||||
0x64, 0xe3, 0xd2, 0x99, 0x40, 0x0e, 0x45, 0xdc, 0xde, 0xd5, 0x35, 0x36,
|
||||
0x35, 0xc2, 0xfb, 0x9a, 0x75, 0x00, 0x35, 0xdb, 0x6a, 0xfb, 0xd4, 0x34,
|
||||
0xe9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d, 0x00, 0x3e, 0x35, 0xcb, 0x7b, 0x0a,
|
||||
0x96, 0x91, 0x17, 0x6a, 0xd2, 0xd0, 0x03, 0x64, 0x6c, 0x2f, 0xb9, 0xa8,
|
||||
0x69, 0xce, 0xdb, 0x9a, 0x9b, 0xd6, 0x80, 0x1f, 0x12, 0xe4, 0xe7, 0xd2,
|
||||
0xa5, 0xa4, 0x51, 0xb4, 0x62, 0x97, 0xa5, 0x00, 0x67, 0xc9, 0xad, 0xd8,
|
||||
0x91, 0x81, 0x72, 0x9f, 0x9d, 0x47, 0xfd, 0xb3, 0x65, 0xff, 0x00, 0x3f,
|
||||
0x29, 0x5f, 0xa0, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad,
|
||||
0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43,
|
||||
0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd7, 0x3f, 0xb7, 0x87, 0x73, 0x6f,
|
||||
0x63, 0x33, 0xe0, 0x28, 0xf5, 0x9b, 0x11, 0xc9, 0xb9, 0x4c, 0xfd, 0x69,
|
||||
0xff, 0x00, 0xdb, 0x96, 0x1f, 0xf3, 0xf5, 0x1f, 0xe7, 0x5f, 0x7d, 0x7f,
|
||||
0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80,
|
||||
0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7,
|
||||
0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e, 0x02, 0x93,
|
||||
0x5b, 0xb1, 0x3c, 0x0b, 0x94, 0xc7, 0xd6, 0x99, 0xfd, 0xb3, 0x65, 0xff,
|
||||
0x00, 0x3f, 0x29, 0xf9, 0xd7, 0xe8, 0x07, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f,
|
||||
0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09,
|
||||
0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0xbd, 0xbc, 0x03, 0xd8,
|
||||
0xcc, 0xf8, 0x0e, 0x3d, 0x6a, 0xc1, 0x47, 0x37, 0x29, 0x9f, 0xad, 0x3b,
|
||||
0xfb, 0x72, 0xc3, 0xfe, 0x7e, 0xa3, 0xfc, 0xeb, 0xef, 0xaf, 0xf8, 0x74,
|
||||
0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1,
|
||||
0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48,
|
||||
0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x19, 0x35, 0xbb, 0x26,
|
||||
0x3c, 0x5c, 0xa6, 0x3e, 0xb4, 0xdf, 0xed, 0x9b, 0x2f, 0xf9, 0xf9, 0x4a,
|
||||
0xfd, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
|
||||
0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
|
||||
0x75, 0xaf, 0xfc, 0x04, 0x86, 0x97, 0xb7, 0x80, 0x7b, 0x19, 0x9f, 0x01,
|
||||
0xa6, 0xb5, 0x60, 0xab, 0xff, 0x00, 0x1f, 0x51, 0xe7, 0xeb, 0x4e, 0xfe,
|
||||
0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0xfb, 0xeb, 0xfe,
|
||||
0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f,
|
||||
0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a,
|
||||
0x3d, 0xbc, 0x03, 0xd8, 0xcc, 0xf8, 0x05, 0xf5, 0xab, 0x26, 0x6f, 0xf8,
|
||||
0xf9, 0x4c, 0x7d, 0x69, 0xbf, 0xdb, 0x36, 0x5f, 0xf3, 0xf2, 0x9f, 0x9d,
|
||||
0x7e, 0x80, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5,
|
||||
0xff, 0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd,
|
||||
0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x80, 0x7b, 0x19, 0x9f,
|
||||
0x02, 0x26, 0xb5, 0x60, 0xab, 0x8f, 0xb5, 0x47, 0xf9, 0xd2, 0xff, 0x00,
|
||||
0x6e, 0x58, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x7d, 0xf5, 0xff, 0x00, 0x0e,
|
||||
0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc,
|
||||
0x3a, 0x5b, 0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e,
|
||||
0xde, 0x01, 0xec, 0x66, 0x7c, 0x00, 0xda, 0xd5, 0x93, 0x1c, 0xfd, 0xa5,
|
||||
0x3f, 0x3a, 0x4f, 0xed, 0x8b, 0x2f, 0xf9, 0xf9, 0x4f, 0xce, 0xbf, 0x40,
|
||||
0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00,
|
||||
0xc0, 0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd,
|
||||
0x6b, 0xff, 0x00, 0x01, 0x21, 0xa7, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
|
||||
0x81, 0x57, 0x5a, 0xb0, 0x51, 0x8f, 0xb5, 0x47, 0xf9, 0xd1, 0xfd, 0xb9,
|
||||
0x61, 0xff, 0x00, 0x3f, 0x49, 0xf9, 0xd7, 0xdf, 0x5f, 0xf0, 0xe9, 0x6f,
|
||||
0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5,
|
||||
0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd2,
|
||||
0xf6, 0xf0, 0x0f, 0x63, 0x33, 0xe0, 0x06, 0xd6, 0xac, 0x98, 0xe7, 0xed,
|
||||
0x29, 0xf9, 0xd2, 0x0d, 0x62, 0xcb, 0xfe, 0x7e, 0x53, 0xf3, 0xaf, 0xd0,
|
||||
0x0f, 0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12,
|
||||
0x1a, 0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff,
|
||||
0x00, 0xc0, 0x48, 0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x51,
|
||||
0xad, 0xd8, 0x01, 0x8f, 0xb5, 0x47, 0xf9, 0xd0, 0x75, 0xcb, 0x0c, 0x7f,
|
||||
0xc7, 0xca, 0x7e, 0x75, 0xf7, 0xd7, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f, 0xf4,
|
||||
0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f,
|
||||
0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7b, 0x78, 0x77, 0x0f, 0x63,
|
||||
0x33, 0xf3, 0xfc, 0xeb, 0x36, 0x44, 0xff, 0x00, 0xc7, 0xca, 0x7e, 0x74,
|
||||
0xa3, 0x58, 0xb1, 0x24, 0x66, 0xe5, 0x31, 0xf5, 0xaf, 0xbf, 0xff, 0x00,
|
||||
0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0,
|
||||
0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
|
||||
0xff, 0x00, 0x01, 0x21, 0xa3, 0xdb, 0xc3, 0xb8, 0x7b, 0x19, 0x9f, 0x02,
|
||||
0xff, 0x00, 0x6d, 0xd8, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x07, 0x5c, 0xb1,
|
||||
0x03, 0x8b, 0x94, 0xcf, 0xd6, 0xbe, 0xfa, 0xff, 0x00, 0x87, 0x4b, 0x78,
|
||||
0x4b, 0xfe, 0x87, 0xdd, 0x6b, 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d,
|
||||
0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f,
|
||||
0x0e, 0xe1, 0xec, 0x66, 0x7e, 0x7f, 0xff, 0x00, 0x6c, 0xd9, 0x7f, 0xcf,
|
||||
0xca, 0x7e, 0x74, 0xab, 0xac, 0x58, 0xe7, 0x9b, 0x94, 0xc7, 0xd6, 0xbe,
|
||||
0xff, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
|
||||
0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
|
||||
0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f, 0x0e, 0xe1, 0xec, 0x66, 0x7c,
|
||||
0x0b, 0xfd, 0xb9, 0x61, 0xff, 0x00, 0x3f, 0x51, 0xfe, 0x74, 0x8d, 0xae,
|
||||
0x58, 0xed, 0x38, 0xb9, 0x4c, 0xfd, 0x6b, 0xef, 0xbf, 0xf8, 0x74, 0xb7,
|
||||
0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1, 0xd2,
|
||||
0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48, 0x68,
|
||||
0xf6, 0xf0, 0xee, 0x1e, 0xc6, 0x67, 0xe7, 0xff, 0x00, 0xf6, 0xc5, 0x97,
|
||||
0xfc, 0xfc, 0xa7, 0xe7, 0x4e, 0x4d, 0x62, 0xc7, 0x77, 0x37, 0x29, 0xf9,
|
||||
0xd7, 0xdf, 0xdf, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f,
|
||||
0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee,
|
||||
0xb5, 0xff, 0x00, 0x80, 0x90, 0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
|
||||
0x81, 0x7f, 0xb7, 0x2c, 0x3f, 0xe7, 0xea, 0x3f, 0xce, 0x91, 0xf5, 0xcb,
|
||||
0x1c, 0x71, 0x72, 0x9f, 0x9d, 0x7d, 0xf7, 0xff, 0x00, 0x0e, 0x96, 0xf0,
|
||||
0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc, 0x3a, 0x5b,
|
||||
0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e, 0xde, 0x1d,
|
||||
0xc3, 0xd8, 0xcc, 0xfc, 0xff, 0x00, 0xfe, 0xd9, 0xb2, 0xff, 0x00, 0x9f,
|
||||
0x94, 0xfc, 0xe9, 0xd1, 0xeb, 0x36, 0x20, 0xe4, 0xdc, 0xa7, 0xe7, 0x5f,
|
||||
0x7f, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff,
|
||||
0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f,
|
||||
0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e,
|
||||
0x05, 0xfe, 0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0x6c,
|
||||
0x9a, 0xdd, 0x89, 0x18, 0x17, 0x29, 0xf9, 0xd7, 0xdf, 0x9f, 0xf0, 0xe9,
|
||||
0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3,
|
||||
0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90,
|
||||
0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf, 0xbc, 0xa8, 0xa2, 0x8a, 0xf3,
|
||||
0x0e, 0xf0, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
|
||||
0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
|
||||
0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0xa0, 0xbb, 0xbd, 0xb7, 0xb0,
|
||||
0x88, 0x49, 0x73, 0x3c, 0x56, 0xf1, 0x96, 0x0a, 0x1e, 0x57, 0x0a, 0x09,
|
||||
0x3d, 0x06, 0x4f, 0x7a, 0x9e, 0x95, 0xd3, 0x76, 0xea, 0x01, 0x45, 0x14,
|
||||
0x53, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x82, 0xda, 0xf6, 0xde,
|
||||
0xf0, 0xca, 0x2d, 0xe7, 0x8a, 0x73, 0x13, 0x98, 0xe4, 0xf2, 0xdc, 0x36,
|
||||
0xc6, 0x1d, 0x54, 0xe3, 0xa1, 0xf6, 0xa4, 0xda, 0x4e, 0xcc, 0x09, 0xe8,
|
||||
0xa2, 0x8a, 0x60, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
|
||||
0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
|
||||
0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x02, 0xb8,
|
||||
0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
|
||||
0x01, 0x70, 0xa2, 0x8a, 0x28, 0x18, 0x51, 0x45, 0x14, 0x0a, 0xe1, 0x45,
|
||||
0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb9, 0xca, 0xfc, 0x4a, 0xf0,
|
||||
0x52, 0x78, 0xef, 0xc2, 0xb7, 0x1a, 0x76, 0xef, 0x2e, 0xe5, 0x4f, 0x9d,
|
||||
0x6c, 0xe4, 0xe0, 0x09, 0x00, 0x38, 0xcf, 0xb1, 0xc9, 0x1f, 0x8e, 0x7b,
|
||||
0x57, 0x3d, 0xf0, 0x5b, 0xc7, 0x53, 0x6b, 0xba, 0x6c, 0xda, 0x16, 0xaa,
|
||||
0x5a, 0x3d, 0x73, 0x4a, 0xfd, 0xd4, 0x8b, 0x2f, 0xdf, 0x91, 0x01, 0xc0,
|
||||
0x27, 0xdc, 0x1e, 0x0f, 0xe0, 0x7b, 0xd7, 0xa3, 0x5c, 0xdc, 0xc5, 0x67,
|
||||
0x04, 0x93, 0xcf, 0x2a, 0x43, 0x0c, 0x60, 0xb3, 0xc9, 0x23, 0x05, 0x55,
|
||||
0x1e, 0xa4, 0x9e, 0x95, 0xf3, 0x47, 0xc4, 0x8f, 0x1f, 0xe9, 0x36, 0xdf,
|
||||
0x10, 0xed, 0x3c, 0x41, 0xe1, 0x39, 0x99, 0xaf, 0xa1, 0xe2, 0xea, 0x42,
|
||||
0x98, 0x82, 0x72, 0x38, 0xe3, 0x90, 0x4e, 0x46, 0x41, 0xe9, 0x9c, 0x0c,
|
||||
0x7a, 0xd7, 0xc4, 0x67, 0x98, 0x9a, 0x59, 0x3e, 0x26, 0x9e, 0x64, 0xa6,
|
||||
0x93, 0x7e, 0xec, 0xe3, 0x7d, 0x65, 0x1e, 0xe9, 0x77, 0x8b, 0xd7, 0xd3,
|
||||
0x4b, 0x99, 0x4d, 0xa8, 0xbe, 0x63, 0xe9, 0xca, 0x2b, 0xe4, 0x3d, 0x73,
|
||||
0xe3, 0x3f, 0x8b, 0xb5, 0xc6, 0x6d, 0xfa, 0xb4, 0x96, 0x71, 0x9e, 0x91,
|
||||
0x59, 0x0f, 0x28, 0x0f, 0xc4, 0x7c, 0xdf, 0x99, 0xae, 0x56, 0xe7, 0x5a,
|
||||
0xd4, 0x6f, 0x18, 0xb5, 0xc5, 0xfd, 0xd4, 0xec, 0x7b, 0xc9, 0x33, 0x31,
|
||||
0xfd, 0x4d, 0x78, 0x75, 0xf8, 0xfb, 0x0b, 0x07, 0x6a, 0x14, 0x65, 0x25,
|
||||
0xe6, 0xd2, 0xff, 0x00, 0x32, 0x1d, 0x75, 0xd1, 0x1f, 0x73, 0x51, 0x5f,
|
||||
0x0b, 0xdb, 0xea, 0xf7, 0xf6, 0xad, 0xba, 0x0b, 0xdb, 0x88, 0x58, 0x77,
|
||||
0x8e, 0x56, 0x53, 0xfa, 0x1a, 0xe9, 0xf4, 0x5f, 0x8b, 0xfe, 0x2e, 0xd0,
|
||||
0xd9, 0x7c, 0xad, 0x66, 0x7b, 0x84, 0x1f, 0xf2, 0xce, 0xec, 0xf9, 0xc0,
|
||||
0xff, 0x00, 0xdf, 0x59, 0x23, 0xf0, 0x34, 0xa8, 0x71, 0xf6, 0x1a, 0x4e,
|
||||
0xd5, 0xa8, 0x4a, 0x2b, 0xc9, 0xa7, 0xfe, 0x40, 0xab, 0xae, 0xa8, 0xfa,
|
||||
0x13, 0xe2, 0xff, 0x00, 0x8f, 0xcf, 0x82, 0xfc, 0x3e, 0x21, 0xb3, 0x6d,
|
||||
0xda, 0xcd, 0xfe, 0x62, 0xb5, 0x45, 0xe5, 0x97, 0xb1, 0x7c, 0x7b, 0x67,
|
||||
0x8f, 0x72, 0x3d, 0xea, 0x5f, 0x84, 0x7e, 0x05, 0x6f, 0x04, 0x78, 0x60,
|
||||
0x2d, 0xd1, 0x2d, 0xa9, 0xde, 0xb0, 0x9e, 0xe8, 0x93, 0x9d, 0xad, 0x8e,
|
||||
0x17, 0xf0, 0x1d, 0x4f, 0xa9, 0x35, 0xe2, 0x5e, 0x13, 0xf8, 0x89, 0x61,
|
||||
0xac, 0xfc, 0x49, 0x8f, 0xc4, 0x3e, 0x30, 0x76, 0xcc, 0x68, 0x16, 0xd8,
|
||||
0x43, 0x19, 0x68, 0x61, 0x61, 0xd0, 0x91, 0x92, 0x40, 0x1c, 0x9e, 0x33,
|
||||
0xc9, 0xcd, 0x7d, 0x3b, 0x63, 0x7f, 0x6d, 0xaa, 0x5a, 0x45, 0x75, 0x69,
|
||||
0x3c, 0x77, 0x36, 0xd2, 0x8d, 0xc9, 0x2c, 0x4c, 0x19, 0x58, 0x7b, 0x11,
|
||||
0x5e, 0xde, 0x4d, 0x8b, 0xa3, 0x9d, 0xe3, 0x2a, 0x66, 0x1c, 0xe9, 0xf2,
|
||||
0x5e, 0x30, 0x8f, 0x58, 0xae, 0xb2, 0x6b, 0xbc, 0xbf, 0x05, 0xa1, 0x50,
|
||||
0x6a, 0x6f, 0x98, 0xb1, 0x45, 0x14, 0x57, 0xdc, 0x9b, 0x5c, 0x28, 0xa2,
|
||||
0x8a, 0x02, 0xe1, 0x45, 0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb8,
|
||||
0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
|
||||
0x01, 0x70, 0xa2, 0x8a, 0x28, 0x0b, 0x8d, 0xcd, 0x19, 0xa6, 0xe4, 0x51,
|
||||
0x91, 0x55, 0x62, 0x47, 0x66, 0x8c, 0xd3, 0x72, 0x28, 0xc8, 0xa2, 0xc0,
|
||||
0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x01, 0xd9, 0xa3, 0x34,
|
||||
0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e, 0xcd, 0x19, 0xa6, 0xe4, 0x52, 0xe4,
|
||||
0x51, 0x60, 0xb8, 0xb9, 0xa3, 0x34, 0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e,
|
||||
0xdd, 0x46, 0x69, 0xb9, 0x14, 0x64, 0x51, 0x60, 0x1d, 0x9a, 0xa7, 0xac,
|
||||
0x6b, 0x16, 0x9a, 0x0e, 0x9b, 0x71, 0xa8, 0x5f, 0x4c, 0x20, 0xb5, 0x81,
|
||||
0x37, 0xbb, 0x9e, 0xc3, 0xd0, 0x7a, 0x93, 0xd0, 0x0a, 0xb5, 0x91, 0x5f,
|
||||
0x39, 0xfe, 0xd1, 0x1e, 0x37, 0x7d, 0x4b, 0x5a, 0x4f, 0x0f, 0x5b, 0x48,
|
||||
0x45, 0xa5, 0x96, 0x1e, 0x70, 0xa7, 0xef, 0xca, 0x46, 0x40, 0x3f, 0xee,
|
||||
0x83, 0xf9, 0x93, 0xe9, 0x5e, 0x06, 0x79, 0x9a, 0xc3, 0x27, 0xc1, 0x4b,
|
||||
0x12, 0xd5, 0xe5, 0xb4, 0x57, 0x76, 0xff, 0x00, 0xab, 0xbf, 0x24, 0x44,
|
||||
0xe5, 0xca, 0xae, 0x72, 0xbf, 0x12, 0xbe, 0x2a, 0xea, 0x3e, 0x3e, 0xbd,
|
||||
0x78, 0xd5, 0x9e, 0xd3, 0x48, 0x46, 0xfd, 0xd5, 0xa2, 0x9f, 0xbd, 0xe8,
|
||||
0xcf, 0xea, 0x7f, 0x41, 0xdb, 0xd4, 0xc3, 0xe0, 0x5f, 0x85, 0x1a, 0xd7,
|
||||
0x8f, 0xed, 0xe6, 0xb9, 0xb1, 0xf2, 0x2d, 0xed, 0x22, 0x6d, 0x86, 0x7b,
|
||||
0x96, 0x21, 0x59, 0xb1, 0x9c, 0x0c, 0x02, 0x4f, 0x51, 0xf9, 0xd7, 0x19,
|
||||
0x5e, 0xcd, 0xf0, 0x73, 0xe3, 0x16, 0x97, 0xe1, 0x0d, 0x06, 0x4d, 0x23,
|
||||
0x57, 0x49, 0x63, 0x44, 0x95, 0xa5, 0x86, 0x78, 0x53, 0x78, 0x21, 0xba,
|
||||
0xab, 0x0e, 0xb9, 0xcf, 0x7f, 0x7f, 0x6a, 0xfc, 0x1b, 0x2e, 0xa9, 0x87,
|
||||
0xcd, 0xb3, 0x2f, 0x69, 0x9c, 0xd5, 0x6a, 0x2e, 0xfa, 0xde, 0xda, 0xf4,
|
||||
0x57, 0xe8, 0xbf, 0xe1, 0x8e, 0x48, 0xda, 0x52, 0xf7, 0x8f, 0x30, 0xf1,
|
||||
0x57, 0x85, 0x75, 0x0f, 0x06, 0xeb, 0x12, 0x69, 0xba, 0x94, 0x42, 0x3b,
|
||||
0x84, 0x01, 0x83, 0x21, 0xca, 0xba, 0x9e, 0x8c, 0xa7, 0xb8, 0xac, 0x8a,
|
||||
0xed, 0x3e, 0x2c, 0xf8, 0xee, 0x1f, 0x1f, 0xf8, 0x9c, 0x5e, 0xda, 0xc2,
|
||||
0xf0, 0xda, 0x41, 0x08, 0x82, 0x2f, 0x33, 0x01, 0xd8, 0x02, 0x49, 0x63,
|
||||
0xe9, 0xc9, 0x3c, 0x57, 0x17, 0x5e, 0x26, 0x3e, 0x9e, 0x1e, 0x96, 0x2a,
|
||||
0xa4, 0x30, 0xb2, 0xe6, 0xa6, 0x9b, 0xb3, 0xee, 0x88, 0x76, 0xbe, 0x81,
|
||||
0x5a, 0x1a, 0x06, 0x83, 0x7b, 0xe2, 0x7d, 0x5e, 0xdf, 0x4d, 0xd3, 0xe2,
|
||||
0xf3, 0xae, 0xa7, 0x38, 0x55, 0xce, 0x00, 0x00, 0x64, 0x92, 0x7b, 0x00,
|
||||
0x39, 0xac, 0xfa, 0xea, 0x3e, 0x1b, 0x78, 0xc1, 0x7c, 0x0d, 0xe2, 0xcb,
|
||||
0x5d, 0x52, 0x58, 0x4c, 0xf6, 0xe1, 0x5a, 0x39, 0x51, 0x3e, 0xf6, 0xd6,
|
||||
0x18, 0x24, 0x7b, 0x8e, 0x0d, 0x67, 0x83, 0x85, 0x1a, 0x98, 0x8a, 0x70,
|
||||
0xc4, 0x4b, 0x96, 0x0d, 0xae, 0x67, 0xd9, 0x5f, 0x50, 0x56, 0xbe, 0xa6,
|
||||
0x97, 0x8d, 0x7e, 0x0e, 0xeb, 0xde, 0x06, 0xd3, 0x17, 0x50, 0xbb, 0x36,
|
||||
0xf7, 0x56, 0x99, 0x0b, 0x24, 0x96, 0xae, 0x4f, 0x96, 0x4f, 0x4d, 0xc0,
|
||||
0x81, 0xc1, 0x3c, 0x66, 0xa9, 0xfc, 0x3e, 0xf8, 0x93, 0xaa, 0x78, 0x03,
|
||||
0x50, 0x0f, 0x6c, 0xe6, 0x7b, 0x07, 0x6f, 0xdf, 0xd9, 0x3b, 0x7c, 0x8e,
|
||||
0x3d, 0x47, 0xa3, 0x7b, 0xfe, 0x79, 0xaf, 0x45, 0xf8, 0xad, 0xf1, 0xb3,
|
||||
0x47, 0xf1, 0x27, 0x85, 0x26, 0xd2, 0x34, 0x84, 0x9a, 0x67, 0xbb, 0x2b,
|
||||
0xe6, 0xcb, 0x34, 0x7b, 0x04, 0x6a, 0x18, 0x36, 0x07, 0xa9, 0xc8, 0x1e,
|
||||
0xd5, 0xe1, 0x95, 0xf4, 0x39, 0xab, 0xc2, 0x65, 0x79, 0x84, 0x67, 0x93,
|
||||
0x55, 0x6d, 0x24, 0x9d, 0xd3, 0xbd, 0x9f, 0x55, 0x7e, 0xaa, 0xd6, 0xbe,
|
||||
0xfb, 0xd8, 0xb9, 0x5a, 0x32, 0xf7, 0x59, 0xf6, 0xef, 0x86, 0xbc, 0x49,
|
||||
0x63, 0xe2, 0xbd, 0x1a, 0xdf, 0x53, 0xd3, 0xe5, 0xf3, 0x2d, 0xe6, 0x1d,
|
||||
0xfe, 0xf2, 0x1e, 0xea, 0xc3, 0xb1, 0x15, 0xa9, 0x9a, 0xf9, 0x7b, 0xe0,
|
||||
0x27, 0x8d, 0xe4, 0xf0, 0xef, 0x8a, 0x53, 0x4a, 0x9e, 0x43, 0xfd, 0x9f,
|
||||
0xa9, 0x30, 0x8f, 0x69, 0x3c, 0x24, 0xdf, 0xc0, 0xc3, 0xeb, 0xf7, 0x7f,
|
||||
0x11, 0xe9, 0x5f, 0x4f, 0xe4, 0x57, 0xee, 0x3c, 0x3f, 0x9b, 0xc7, 0x39,
|
||||
0xc1, 0x2a, 0xed, 0x5a, 0x6b, 0x49, 0x2f, 0x3f, 0xf2, 0x7b, 0xfe, 0x1d,
|
||||
0x0e, 0xb8, 0x4f, 0x99, 0x5c, 0x76, 0x4d, 0x19, 0xa6, 0xe4, 0x51, 0x91,
|
||||
0x5f, 0x4b, 0x62, 0xc7, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
|
||||
0x2e, 0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x0b, 0x8e, 0xcd,
|
||||
0x19, 0xa6, 0xe4, 0x51, 0x91, 0x45, 0x80, 0x76, 0x68, 0xcd, 0x37, 0x34,
|
||||
0x64, 0x51, 0x60, 0xb8, 0xec, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
|
||||
0x07, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58, 0x06, 0x6e, 0xa3,
|
||||
0x75, 0x37, 0x34, 0x66, 0xae, 0xc4, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73,
|
||||
0x46, 0x68, 0xb0, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73, 0x46, 0x68, 0xb0,
|
||||
0x5c, 0x76, 0xea, 0x37, 0x53, 0x72, 0x28, 0xcd, 0x16, 0x0b, 0x8e, 0xdd,
|
||||
0x46, 0xea, 0x6e, 0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0x6e,
|
||||
0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0xc4, 0xf1, 0x57, 0x8c,
|
||||
0x34, 0xaf, 0x06, 0x69, 0xff, 0x00, 0x6b, 0xd5, 0x2e, 0x44, 0x28, 0xc7,
|
||||
0x08, 0x8a, 0x37, 0x3c, 0x87, 0xd1, 0x47, 0x7f, 0xe5, 0x5c, 0x0d, 0x9f,
|
||||
0xed, 0x1f, 0xe1, 0xcb, 0x8b, 0xc1, 0x14, 0xd6, 0x97, 0xf6, 0xb0, 0x93,
|
||||
0x81, 0x3b, 0xa2, 0xb0, 0x1e, 0xe4, 0x06, 0x27, 0xf2, 0xcd, 0x78, 0xf8,
|
||||
0xac, 0xdf, 0x2f, 0xc0, 0xd4, 0x54, 0x71, 0x35, 0xa3, 0x19, 0x3e, 0x8d,
|
||||
0xfe, 0x7d, 0xbe, 0x64, 0xb9, 0x25, 0xb9, 0xeb, 0x05, 0xf6, 0x82, 0x4f,
|
||||
0x41, 0x5f, 0x10, 0xeb, 0x7a, 0x93, 0xeb, 0x3a, 0xcd, 0xf5, 0xfc, 0x84,
|
||||
0x97, 0xb9, 0x9d, 0xe6, 0x39, 0xff, 0x00, 0x69, 0x89, 0xfe, 0xb5, 0xf6,
|
||||
0xad, 0x8e, 0xa1, 0x6b, 0xab, 0x58, 0xc5, 0x75, 0x69, 0x34, 0x77, 0x36,
|
||||
0xb3, 0x2e, 0xe4, 0x91, 0x0e, 0x55, 0x85, 0x78, 0x5f, 0xfc, 0x2d, 0x5f,
|
||||
0x87, 0x3f, 0xf4, 0x25, 0x27, 0xfe, 0x00, 0xdb, 0xff, 0x00, 0x8d, 0x7c,
|
||||
0x67, 0x18, 0xe1, 0xa8, 0x63, 0x61, 0x87, 0x55, 0x31, 0x31, 0xa7, 0x1f,
|
||||
0x79, 0xab, 0xdd, 0xf3, 0x7c, 0x3a, 0xab, 0x76, 0xfd, 0x4c, 0xea, 0x59,
|
||||
0xdb, 0x53, 0xc4, 0x68, 0xaf, 0x6e, 0xff, 0x00, 0x85, 0xab, 0xf0, 0xe7,
|
||||
0xfe, 0x84, 0xa4, 0xff, 0x00, 0xc0, 0x1b, 0x7f, 0xf1, 0xa3, 0xfe, 0x16,
|
||||
0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
|
||||
0xc6, 0xbf, 0x33, 0xfe, 0xc5, 0xc0, 0xff, 0x00, 0xd0, 0x7c, 0x3e, 0xe9,
|
||||
0x7f, 0x91, 0x8f, 0x2a, 0xee, 0x78, 0x8d, 0x15, 0xed, 0xdf, 0xf0, 0xb5,
|
||||
0x7e, 0x1c, 0xff, 0x00, 0xd0, 0x94, 0x9f, 0xf8, 0x03, 0x6f, 0xfe, 0x34,
|
||||
0x7f, 0xc2, 0xd5, 0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d,
|
||||
0xbf, 0xf8, 0xd1, 0xfd, 0x8b, 0x81, 0xff, 0x00, 0xa0, 0xf8, 0x7d, 0xd2,
|
||||
0xff, 0x00, 0x20, 0xe5, 0x5d, 0xcf, 0x11, 0xa2, 0xbd, 0xbb, 0xfe, 0x16,
|
||||
0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
|
||||
0xc6, 0x8f, 0xf8, 0x5a, 0xbf, 0x0e, 0x7f, 0xe8, 0x4a, 0x4f, 0xfc, 0x01,
|
||||
0xb7, 0xff, 0x00, 0x1a, 0x3f, 0xb1, 0x70, 0x3f, 0xf4, 0x1f, 0x0f, 0xba,
|
||||
0x5f, 0xe4, 0x1c, 0xab, 0xb9, 0xe2, 0x34, 0x57, 0xb7, 0x7f, 0xc2, 0xd5,
|
||||
0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd1,
|
||||
0xff, 0x00, 0x0b, 0x57, 0xe1, 0xcf, 0xfd, 0x09, 0x49, 0xff, 0x00, 0x80,
|
||||
0x36, 0xff, 0x00, 0xe3, 0x47, 0xf6, 0x2e, 0x07, 0xfe, 0x83, 0xe1, 0xf7,
|
||||
0x4b, 0xfc, 0x83, 0x95, 0x77, 0x3c, 0x52, 0x09, 0xde, 0xda, 0x78, 0xe6,
|
||||
0x89, 0x8a, 0x49, 0x1b, 0x07, 0x56, 0x1d, 0x41, 0x07, 0x20, 0xd7, 0xdb,
|
||||
0xfa, 0x5d, 0xf0, 0xd4, 0x74, 0xdb, 0x4b, 0xb0, 0x30, 0x27, 0x85, 0x25,
|
||||
0x03, 0xfd, 0xe5, 0x07, 0xfa, 0xd7, 0x85, 0xff, 0x00, 0xc2, 0xd5, 0xf8,
|
||||
0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd7, 0xb6,
|
||||
0x69, 0x1a, 0x95, 0xa5, 0xc7, 0x87, 0xec, 0xaf, 0xe1, 0x55, 0xb3, 0xb1,
|
||||
0x7b, 0x54, 0x99, 0x11, 0xf0, 0x82, 0x28, 0xca, 0x02, 0x01, 0xec, 0x30,
|
||||
0x3f, 0x0e, 0x2b, 0xf4, 0x7e, 0x0e, 0xc2, 0xd0, 0xc1, 0xce, 0xbc, 0x69,
|
||||
0x62, 0x63, 0x51, 0x34, 0x9b, 0x4a, 0xfa, 0x5a, 0xfa, 0xeb, 0xea, 0x6d,
|
||||
0x4e, 0xca, 0xfa, 0x9a, 0x5b, 0xa8, 0xdd, 0x5e, 0x57, 0xab, 0xfe, 0xd1,
|
||||
0x3e, 0x1b, 0xd3, 0xaf, 0x1a, 0x0b, 0x68, 0x6e, 0xf5, 0x15, 0x53, 0x83,
|
||||
0x34, 0x28, 0xaa, 0x87, 0xe9, 0xb8, 0x82, 0x7f, 0x2a, 0xeb, 0xbc, 0x1b,
|
||||
0xf1, 0x07, 0x45, 0xf1, 0xcd, 0xbb, 0xbe, 0x99, 0x70, 0x7c, 0xe8, 0xc6,
|
||||
0x64, 0xb6, 0x98, 0x6d, 0x91, 0x07, 0xa9, 0x1d, 0xc7, 0xb8, 0xc8, 0xaf,
|
||||
0xb7, 0xc3, 0xe7, 0x19, 0x76, 0x2a, 0xb7, 0xd5, 0xe8, 0x56, 0x8c, 0xa7,
|
||||
0xd9, 0x3f, 0xcb, 0xbf, 0xc8, 0xd1, 0x49, 0x3d, 0x2e, 0x74, 0xdb, 0xa8,
|
||||
0xcd, 0x37, 0x34, 0x64, 0x57, 0xb2, 0x55, 0xc7, 0x6e, 0xa3, 0x75, 0x37,
|
||||
0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b,
|
||||
0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e,
|
||||
0xa3, 0x75, 0x37, 0x34, 0x64, 0x51, 0x60, 0xb8, 0xed, 0xd4, 0x6e, 0xa6,
|
||||
0xe4, 0x51, 0x9a, 0x2c, 0x17, 0x1b, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75,
|
||||
0x55, 0x88, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d, 0xd4, 0x58, 0x2e,
|
||||
0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15, 0xc9, 0x32, 0x28,
|
||||
0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35, 0x1e, 0xea,
|
||||
0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8c, 0xd3, 0xb0,
|
||||
0x5c, 0xf9, 0x7b, 0xe3, 0xb6, 0xaf, 0x3e, 0xa5, 0xf1, 0x0e, 0xf2, 0xde,
|
||||
0x47, 0x26, 0x1b, 0x24, 0x48, 0x62, 0x4e, 0xc0, 0x15, 0x0c, 0x4f, 0xe2,
|
||||
0x58, 0xfe, 0x95, 0xe7, 0x95, 0xda, 0x7c, 0x64, 0xff, 0x00, 0x92, 0x97,
|
||||
0xad, 0xff, 0x00, 0xbf, 0x1f, 0xfe, 0x8a, 0x4a, 0xe2, 0xeb, 0xf9, 0x47,
|
||||
0x3a, 0x9c, 0xaa, 0x66, 0x78, 0x99, 0x49, 0xdd, 0xf3, 0xcb, 0xf0, 0x6d,
|
||||
0x23, 0x92, 0x5b, 0x9e, 0xf7, 0xfb, 0x34, 0xeb, 0x13, 0xcd, 0x67, 0xac,
|
||||
0xe9, 0xb2, 0x39, 0x6b, 0x78, 0x1a, 0x39, 0xa2, 0x04, 0xfd, 0xd2, 0xdb,
|
||||
0x83, 0x0f, 0xc7, 0x68, 0xfd, 0x6b, 0xc1, 0x2b, 0xda, 0xff, 0x00, 0x66,
|
||||
0x73, 0x8b, 0xed, 0x7f, 0xfe, 0xb9, 0xc3, 0xfc, 0xde, 0xbc, 0x52, 0xbd,
|
||||
0x8c, 0xd2, 0x72, 0x9e, 0x4b, 0x97, 0x39, 0x3b, 0xdb, 0xda, 0xaf, 0x92,
|
||||
0x92, 0xb1, 0x4f, 0xe1, 0x41, 0x45, 0x14, 0x57, 0xc6, 0x90, 0x14, 0x51,
|
||||
0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x15, 0xef,
|
||||
0x7f, 0x13, 0xf5, 0x89, 0xf4, 0xef, 0x82, 0xbe, 0x19, 0xb6, 0x81, 0xca,
|
||||
0x0b, 0xc8, 0x2d, 0x62, 0x94, 0x83, 0xd5, 0x04, 0x3b, 0x88, 0xfc, 0x48,
|
||||
0x15, 0xe0, 0x95, 0xed, 0x7f, 0x17, 0x0f, 0xfc, 0x5a, 0x5f, 0x05, 0xff,
|
||||
0x00, 0xd7, 0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x96, 0x47, 0x39, 0x43, 0x03,
|
||||
0x98, 0x4a, 0x2e, 0xcf, 0x91, 0x7e, 0x32, 0xb3, 0xfc, 0x0a, 0x8e, 0xcc,
|
||||
0xf1, 0x4a, 0xe9, 0xbe, 0x1a, 0x6a, 0xf3, 0xe8, 0xbe, 0x3a, 0xd1, 0x67,
|
||||
0x81, 0xca, 0x99, 0x2e, 0x52, 0x07, 0x00, 0xfd, 0xe4, 0x76, 0x0a, 0xc0,
|
||||
0xfe, 0x07, 0xf4, 0xae, 0x66, 0xb6, 0x3c, 0x1b, 0xff, 0x00, 0x23, 0x7e,
|
||||
0x87, 0xff, 0x00, 0x5f, 0xd0, 0x7f, 0xe8, 0xc5, 0xaf, 0x9b, 0xc0, 0xce,
|
||||
0x54, 0xf1, 0x54, 0xa7, 0x07, 0x66, 0xa4, 0xbf, 0x31, 0x2d, 0xcf, 0xb4,
|
||||
0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xaf, 0xeb, 0x9b, 0x1d, 0x57, 0x24,
|
||||
0xcd, 0x19, 0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35,
|
||||
0x1e, 0xea, 0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d,
|
||||
0xd4, 0x58, 0x2e, 0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15,
|
||||
0xc9, 0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xa2, 0xc3, 0xb8, 0xdd, 0xd4,
|
||||
0x9b, 0xa9, 0xbb, 0xa8, 0xdd, 0x5a, 0x19, 0xdc, 0x7e, 0xea, 0x4d, 0xd4,
|
||||
0xdd, 0xd4, 0x6e, 0xa0, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e,
|
||||
0xa0, 0x77, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e, 0xa4, 0x2b, 0x8f,
|
||||
0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0xc2, 0xe3, 0xb7, 0x52, 0xee,
|
||||
0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb9, 0xf2, 0x9f, 0xc6, 0x3f, 0xf9, 0x29,
|
||||
0x5a, 0xdf, 0xfb, 0xf1, 0xff, 0x00, 0xe8, 0xb4, 0xae, 0x32, 0xbb, 0x2f,
|
||||
0x8c, 0x5c, 0xfc, 0x49, 0xd6, 0xff, 0x00, 0xdf, 0x8f, 0xff, 0x00, 0x45,
|
||||
0xa5, 0x71, 0xb5, 0xfc, 0x99, 0x9c, 0x7f, 0xc8, 0xcb, 0x13, 0xfe, 0x39,
|
||||
0xff, 0x00, 0xe9, 0x4c, 0xc1, 0xee, 0x7b, 0x57, 0xec, 0xd2, 0x71, 0x7d,
|
||||
0xaf, 0x7f, 0xd7, 0x38, 0x7f, 0x9b, 0xd7, 0x8a, 0xd7, 0xb4, 0x7e, 0xcd,
|
||||
0x67, 0x17, 0xda, 0xf7, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78, 0xbd, 0x7b,
|
||||
0x19, 0x97, 0xfc, 0x89, 0x32, 0xef, 0xfb, 0x8b, 0xff, 0x00, 0xa5, 0x21,
|
||||
0xbd, 0x90, 0x51, 0x45, 0x15, 0xf2, 0x02, 0x0a, 0x28, 0xa2, 0x80, 0x0a,
|
||||
0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0xf6, 0xaf, 0x8b, 0x47,
|
||||
0x3f, 0x09, 0x7c, 0x17, 0xff, 0x00, 0x5c, 0xe0, 0xff, 0x00, 0xd1, 0x15,
|
||||
0xe2, 0xb5, 0xed, 0x1f, 0x16, 0x4f, 0xfc, 0x5a, 0x6f, 0x06, 0x7f, 0xd7,
|
||||
0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x7e, 0x4d, 0xff, 0x00, 0x22, 0xfc, 0xc3,
|
||||
0xfc, 0x11, 0xff, 0x00, 0xd2, 0x90, 0xd6, 0xcc, 0xf1, 0x7a, 0xd8, 0xf0,
|
||||
0x67, 0xfc, 0x8e, 0x1a, 0x17, 0xfd, 0x7f, 0xc1, 0xff, 0x00, 0xa3, 0x16,
|
||||
0xb1, 0xeb, 0x63, 0xc1, 0xdf, 0xf2, 0x37, 0x68, 0x7f, 0xf5, 0xfd, 0x07,
|
||||
0xfe, 0x8c, 0x5a, 0xf9, 0xbc, 0x27, 0xfb, 0xcd, 0x3f, 0xf1, 0x2f, 0xcc,
|
||||
0x48, 0xfb, 0x2b, 0x75, 0x1b, 0xa9, 0x9b, 0xa8, 0xdd, 0x5f, 0xd8, 0x16,
|
||||
0x37, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb8, 0xed,
|
||||
0xd4, 0xbb, 0xa9, 0x9b, 0xa8, 0xdd, 0x4c, 0x2e, 0x3f, 0x75, 0x26, 0xea,
|
||||
0x6e, 0xea, 0x37, 0x52, 0x0b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d,
|
||||
0xd4, 0xec, 0x3b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0x0a,
|
||||
0xe4, 0x74, 0x53, 0x33, 0x4b, 0x93, 0x57, 0x63, 0x3b, 0x8e, 0xa2, 0x9b,
|
||||
0x9a, 0x4c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa3, 0x34, 0x58, 0x2e,
|
||||
0x3f, 0x34, 0x53, 0x33, 0x4b, 0x93, 0x45, 0x82, 0xe3, 0xa8, 0xcd, 0x33,
|
||||
0x34, 0x66, 0x8b, 0x05, 0xc7, 0xd1, 0x4d, 0xc9, 0xa3, 0x26, 0x8b, 0x05,
|
||||
0xcf, 0x96, 0x3e, 0x30, 0x7f, 0xc9, 0x48, 0xd6, 0xbf, 0xdf, 0x8f, 0xff,
|
||||
0x00, 0x45, 0xa5, 0x71, 0xb5, 0xdd, 0xfc, 0x6c, 0xd3, 0xa6, 0xb1, 0xf8,
|
||||
0x85, 0x7f, 0x2c, 0x8a, 0x44, 0x77, 0x4b, 0x1c, 0xd1, 0xb7, 0x66, 0x1b,
|
||||
0x02, 0x9f, 0xd5, 0x4d, 0x70, 0x95, 0xfc, 0x97, 0x9d, 0x42, 0x50, 0xcc,
|
||||
0xf1, 0x31, 0x92, 0xb7, 0xbf, 0x2f, 0xfd, 0x29, 0x90, 0x7b, 0x3f, 0xec,
|
||||
0xdb, 0xff, 0x00, 0x1f, 0xba, 0xef, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78,
|
||||
0xc5, 0x7b, 0x87, 0xec, 0xe3, 0xa7, 0x4d, 0x1c, 0x3a, 0xd5, 0xf3, 0x29,
|
||||
0x58, 0x24, 0x31, 0xc2, 0x8d, 0xfd, 0xe2, 0x37, 0x16, 0xfc, 0xb2, 0x3f,
|
||||
0x3a, 0xf0, 0xfa, 0xf6, 0x73, 0x58, 0x4a, 0x19, 0x26, 0x5b, 0xcc, 0xad,
|
||||
0x7f, 0x6a, 0xff, 0x00, 0xf2, 0x64, 0x01, 0x45, 0x14, 0x57, 0xc6, 0x00,
|
||||
0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00,
|
||||
0x57, 0xb3, 0xfc, 0x57, 0xff, 0x00, 0x92, 0x51, 0xe0, 0xdf, 0xfa, 0xe7,
|
||||
0x07, 0xfe, 0x88, 0xaf, 0x18, 0xaf, 0x70, 0xf8, 0x9b, 0xa7, 0x4d, 0x79,
|
||||
0xf0, 0x77, 0xc3, 0x37, 0x11, 0x29, 0x74, 0xb5, 0x8a, 0xd9, 0xe4, 0xc7,
|
||||
0x65, 0x30, 0xed, 0xcf, 0xe6, 0x40, 0xfc, 0x6b, 0xec, 0xf2, 0x38, 0x4a,
|
||||
0x78, 0x0c, 0xc1, 0x45, 0x5f, 0xdc, 0x5f, 0x84, 0xae, 0xc0, 0xf0, 0xfa,
|
||||
0xd8, 0xf0, 0x6f, 0xfc, 0x8d, 0xfa, 0x1f, 0xfd, 0x7f, 0x41, 0xff, 0x00,
|
||||
0xa3, 0x16, 0xb1, 0xeb, 0xa2, 0xf8, 0x79, 0xa7, 0x4d, 0xaa, 0x78, 0xdf,
|
||||
0x45, 0x86, 0x15, 0x2c, 0xcb, 0x75, 0x1c, 0xad, 0x8e, 0xca, 0x8c, 0x18,
|
||||
0x9f, 0xc8, 0x57, 0xcd, 0x60, 0x61, 0x29, 0xe2, 0xe9, 0x46, 0x2a, 0xed,
|
||||
0xca, 0x3f, 0x9a, 0x03, 0xeb, 0x9c, 0xd1, 0x4c, 0xcd, 0x2e, 0x4d, 0x7f,
|
||||
0x60, 0x58, 0xbb, 0x8e, 0xa2, 0x99, 0x9a, 0x33, 0x45, 0x82, 0xe3, 0xe8,
|
||||
0xa6, 0x66, 0x8c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa5, 0xc9, 0xa2,
|
||||
0xc1, 0x71, 0xd9, 0xa2, 0x9b, 0x93, 0x49, 0x9a, 0x2c, 0x17, 0x1f, 0x45,
|
||||
0x33, 0x34, 0x66, 0x8b, 0x05, 0xc6, 0x6e, 0xa3, 0x75, 0x30, 0x90, 0x3a,
|
||||
0x9c, 0x51, 0x9a, 0xd2, 0xc6, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xda, 0x4c,
|
||||
0xd1, 0x60, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x02, 0x0f, 0x43, 0x9a, 0x37,
|
||||
0x01, 0xdf, 0x14, 0x58, 0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x94, 0x58,
|
||||
0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x80, 0x83, 0xd0, 0xe6, 0x8b, 0x05,
|
||||
0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x3a, 0x9c, 0x51, 0x9a, 0x2c, 0x17,
|
||||
0x31, 0x3c, 0x5d, 0xe0, 0xcd, 0x2f, 0xc6, 0xb6, 0x2b, 0x6f, 0xa8, 0xc4,
|
||||
0x4b, 0x26, 0x4c, 0x53, 0xc6, 0x71, 0x24, 0x64, 0xf5, 0xc1, 0xfe, 0x87,
|
||||
0x8a, 0xe0, 0x6d, 0x3f, 0x67, 0x7d, 0x32, 0x2b, 0xb0, 0xf7, 0x1a, 0xad,
|
||||
0xcc, 0xf6, 0xe0, 0xe7, 0xca, 0x58, 0xd5, 0x09, 0x1e, 0x85, 0xb2, 0x7f,
|
||||
0x95, 0x7a, 0xd5, 0x25, 0x78, 0x38, 0xcc, 0x87, 0x2c, 0xcc, 0x2b, 0x2a,
|
||||
0xf8, 0x9a, 0x2a, 0x52, 0xef, 0xaa, 0xfb, 0xec, 0xd5, 0xfe, 0x77, 0x0b,
|
||||
0x95, 0xf4, 0xad, 0x32, 0xd3, 0x44, 0xb0, 0x86, 0xca, 0xc6, 0x05, 0xb7,
|
||||
0xb6, 0x88, 0x61, 0x23, 0x4e, 0x83, 0xfc, 0x4f, 0xbd, 0x7c, 0x6b, 0x5f,
|
||||
0x69, 0x57, 0xc5, 0xb5, 0xf9, 0x8f, 0x88, 0xb0, 0x8d, 0x38, 0xe0, 0xe1,
|
||||
0x05, 0x64, 0xb9, 0xec, 0x97, 0xfd, 0xb8, 0x34, 0x14, 0x51, 0x45, 0x7e,
|
||||
0x32, 0x30, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
|
||||
0x28, 0x00, 0xaf, 0xad, 0xfc, 0x2b, 0x04, 0x57, 0x9e, 0x06, 0xd1, 0xad,
|
||||
0xe7, 0x8d, 0x66, 0x86, 0x4d, 0x3a, 0x04, 0x78, 0xdc, 0x65, 0x58, 0x18,
|
||||
0xd7, 0x20, 0x8a, 0xf9, 0x22, 0xbe, 0xba, 0xf0, 0x67, 0xfc, 0x89, 0xfa,
|
||||
0x17, 0xfd, 0x78, 0x41, 0xff, 0x00, 0xa2, 0xd6, 0xbf, 0x5c, 0xf0, 0xee,
|
||||
0x2a, 0x58, 0x9c, 0x42, 0x7b, 0x72, 0xaf, 0xcc, 0x47, 0x05, 0xab, 0x7e,
|
||||
0xcf, 0x7a, 0x4d, 0xdd, 0xdb, 0x4b, 0x65, 0xa8, 0x4f, 0x63, 0x13, 0x1c,
|
||||
0xf9, 0x25, 0x04, 0x80, 0x7b, 0x02, 0x48, 0x3f, 0x9e, 0x6b, 0xaf, 0xf0,
|
||||
0x57, 0xc3, 0xcd, 0x27, 0xc0, 0xd1, 0xb9, 0xb3, 0x47, 0x9a, 0xee, 0x41,
|
||||
0xb6, 0x4b, 0xa9, 0xb0, 0x5c, 0x8f, 0x41, 0xe8, 0x3d, 0x87, 0xe3, 0x5d,
|
||||
0x36, 0x69, 0x6b, 0xf5, 0x7c, 0x37, 0x0f, 0xe5, 0x78, 0x3a, 0xff, 0x00,
|
||||
0x59, 0xa1, 0x41, 0x46, 0x7d, 0xf5, 0xd3, 0xd1, 0x6c, 0xbe, 0x49, 0x0a,
|
||||
0xe3, 0xb7, 0x51, 0xba, 0x99, 0x9a, 0x03, 0x03, 0xde, 0xbd, 0xfb, 0x05,
|
||||
0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x06, 0x4f, 0x14, 0x51, 0x60, 0xb8,
|
||||
0xfd, 0xd4, 0x6e, 0xa6, 0xd1, 0x45, 0x82, 0xe3, 0xb7, 0x51, 0xba, 0x98,
|
||||
0x08, 0x3d, 0x0e, 0x68, 0x24, 0x0e, 0xf4, 0x58, 0x2e, 0x3f, 0x75, 0x1b,
|
||||
0xa9, 0x94, 0xb4, 0x58, 0x2e, 0x3b, 0x75, 0x1b, 0xa9, 0x99, 0xa0, 0x10,
|
||||
0x7a, 0x1a, 0x2c, 0x17, 0x31, 0x62, 0xbd, 0x91, 0x46, 0xf7, 0x90, 0x3e,
|
||||
0xd3, 0xf7, 0x1b, 0xa9, 0xad, 0x58, 0xa5, 0x13, 0x46, 0xae, 0xbd, 0x08,
|
||||
0xac, 0x3f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef, 0x91, 0x56, 0x52, 0xf1,
|
||||
0xe3, 0x48, 0x55, 0x42, 0x80, 0x7a, 0x80, 0x3d, 0xeb, 0xb2, 0x70, 0xbe,
|
||||
0xc7, 0x9d, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x36, 0x59, 0x44, 0x31,
|
||||
0xb3, 0xb7, 0x41, 0x49, 0xba, 0xb3, 0x1e, 0xf2, 0x49, 0x12, 0x65, 0x60,
|
||||
0x08, 0x1d, 0x01, 0x1e, 0xf5, 0x84, 0x61, 0xcc, 0x75, 0x4e, 0xa7, 0x22,
|
||||
0x1b, 0x2d, 0xec, 0x8c, 0x0b, 0xa4, 0x81, 0x37, 0x1f, 0xb8, 0xbd, 0x7e,
|
||||
0xb4, 0xb1, 0x5e, 0xc8, 0xa0, 0x3b, 0xb8, 0x7d, 0xa7, 0xee, 0x37, 0x5f,
|
||||
0xad, 0x57, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x14, 0x79, 0xc7, 0xfb,
|
||||
0x89, 0xff, 0x00, 0x7c, 0x8a, 0xeb, 0xe5, 0x56, 0xb5, 0x8e, 0x0e, 0x77,
|
||||
0x7b, 0xdc, 0xdd, 0x8e, 0x41, 0x2a, 0x2b, 0xaf, 0x42, 0x33, 0x4e, 0xac,
|
||||
0xa8, 0xef, 0x1d, 0x3c, 0x85, 0x00, 0x05, 0x3d, 0x40, 0x1e, 0xe6, 0xb4,
|
||||
0x77, 0x57, 0x24, 0xa3, 0xca, 0x77, 0xc2, 0x7c, 0xe8, 0x74, 0x92, 0x08,
|
||||
0xd1, 0x99, 0x8f, 0x00, 0x66, 0xb2, 0xa5, 0xbd, 0x91, 0x81, 0x74, 0x70,
|
||||
0x99, 0x38, 0xd8, 0x3a, 0xfd, 0x69, 0xd2, 0x5e, 0x3b, 0xf9, 0xea, 0x40,
|
||||
0x2a, 0x3a, 0x02, 0x3d, 0xc5, 0x55, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9,
|
||||
0x15, 0xbc, 0x21, 0x6d, 0xce, 0x6a, 0x95, 0x6f, 0xa2, 0x64, 0xf1, 0x5e,
|
||||
0x48, 0xa3, 0x7b, 0x48, 0x1f, 0x69, 0xfb, 0x8d, 0xd4, 0xd6, 0xac, 0x52,
|
||||
0x89, 0xa3, 0x57, 0x5e, 0x86, 0xb0, 0xfc, 0xe3, 0xfd, 0xc4, 0xff, 0x00,
|
||||
0xbe, 0x45, 0x59, 0x4b, 0xc7, 0x8d, 0x61, 0x0a, 0x14, 0x03, 0xd4, 0x01,
|
||||
0xef, 0x44, 0xe1, 0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x15,
|
||||
0x1e, 0xea, 0x5d, 0xd5, 0xcd, 0x63, 0xba, 0xe3, 0xeb, 0xc0, 0xbc, 0x71,
|
||||
0xf0, 0x57, 0x55, 0x83, 0x57, 0x9e, 0xe7, 0x44, 0x85, 0x6f, 0x6c, 0xa6,
|
||||
0x72, 0xe2, 0x25, 0x70, 0xaf, 0x16, 0x4e, 0x76, 0xe0, 0x91, 0x91, 0xe9,
|
||||
0x8a, 0xf7, 0xad, 0xd4, 0x66, 0xbe, 0x7f, 0x39, 0xc8, 0xf0, 0x99, 0xe5,
|
||||
0x18, 0xd2, 0xc4, 0xdd, 0x72, 0xbb, 0xa6, 0xb7, 0x5d, 0xfb, 0xef, 0xe8,
|
||||
0x17, 0xb1, 0xf2, 0xc5, 0xff, 0x00, 0xc3, 0x5f, 0x12, 0xe9, 0x96, 0x53,
|
||||
0x5d, 0xdd, 0x69, 0x52, 0x43, 0x6f, 0x0a, 0x97, 0x92, 0x42, 0xe8, 0x42,
|
||||
0x81, 0xd4, 0xf0, 0x6b, 0x99, 0xaf, 0xaa, 0xfe, 0x21, 0x9c, 0xf8, 0x1f,
|
||||
0x5c, 0xff, 0x00, 0xaf, 0x47, 0xfe, 0x55, 0xf2, 0xa5, 0x7e, 0x01, 0xc5,
|
||||
0x59, 0x1e, 0x1f, 0x22, 0xc4, 0x53, 0xa3, 0x87, 0x93, 0x92, 0x94, 0x6f,
|
||||
0xef, 0x5b, 0xbd, 0xba, 0x24, 0x5a, 0x77, 0x0a, 0xe9, 0xec, 0xbe, 0x19,
|
||||
0xf8, 0x9b, 0x51, 0xb3, 0x86, 0xea, 0xdb, 0x49, 0x92, 0x5b, 0x79, 0x90,
|
||||
0x49, 0x1b, 0x87, 0x40, 0x19, 0x48, 0xc8, 0x3d, 0x6b, 0x98, 0xaf, 0xac,
|
||||
0x3c, 0x08, 0x71, 0xe0, 0xad, 0x0b, 0xfe, 0xbc, 0xa1, 0xff, 0x00, 0xd0,
|
||||
0x05, 0x57, 0x0a, 0xe4, 0x58, 0x7c, 0xf6, 0xbd, 0x5a, 0x58, 0x89, 0x4a,
|
||||
0x2a, 0x2a, 0xfe, 0xed, 0xbb, 0xdb, 0xaa, 0x60, 0xdd, 0x8f, 0x9e, 0xdb,
|
||||
0xe1, 0x4f, 0x8a, 0xd1, 0x4b, 0x1d, 0x1a, 0x50, 0x00, 0xc9, 0x3e, 0x62,
|
||||
0x7f, 0xf1, 0x55, 0xc9, 0xd7, 0xd9, 0x17, 0x4d, 0xfe, 0x8d, 0x37, 0xfb,
|
||||
0x87, 0xf9, 0x57, 0xc6, 0xf5, 0xd1, 0xc5, 0x9c, 0x3d, 0x86, 0xc8, 0x5d,
|
||||
0x05, 0x87, 0x9c, 0xa5, 0xcf, 0xcd, 0x7e, 0x6b, 0x74, 0xb6, 0xd6, 0x4b,
|
||||
0xb8, 0x27, 0x70, 0xae, 0x87, 0x47, 0xf0, 0x07, 0x88, 0x35, 0xfb, 0x04,
|
||||
0xbd, 0xb0, 0xd3, 0x64, 0xb9, 0xb5, 0x72, 0x42, 0xc8, 0xae, 0xa0, 0x12,
|
||||
0x0e, 0x0f, 0x53, 0xeb, 0x5c, 0xf5, 0x7d, 0x27, 0xf0, 0x54, 0xe3, 0xe1,
|
||||
0xed, 0x8f, 0xfd, 0x74, 0x97, 0xff, 0x00, 0x43, 0x35, 0xe7, 0x70, 0xbe,
|
||||
0x4f, 0x43, 0x3c, 0xc6, 0xcb, 0x0d, 0x5e, 0x4d, 0x25, 0x16, 0xf4, 0xb5,
|
||||
0xee, 0x9a, 0x5d, 0x53, 0xee, 0x0d, 0xd8, 0xf3, 0x1f, 0x0d, 0x7c, 0x12,
|
||||
0xd7, 0xb5, 0x3d, 0x42, 0x31, 0xa9, 0x40, 0x34, 0xdb, 0x20, 0xc0, 0xc8,
|
||||
0xee, 0xea, 0xce, 0x47, 0x70, 0xa0, 0x13, 0xcf, 0xb9, 0xe2, 0xbe, 0x87,
|
||||
0xb7, 0x82, 0x3b, 0x4b, 0x78, 0xa0, 0x89, 0x42, 0x45, 0x12, 0x84, 0x45,
|
||||
0x1d, 0x80, 0x18, 0x02, 0x97, 0x34, 0x9b, 0xab, 0xfa, 0x07, 0x25, 0xe1,
|
||||
0xfc, 0x1e, 0x45, 0x09, 0x47, 0x0d, 0x76, 0xe5, 0xbb, 0x7a, 0xbd, 0x36,
|
||||
0x5a, 0x24, 0xad, 0xf2, 0x22, 0xf7, 0x24, 0xcd, 0x19, 0xa8, 0xf7, 0x51,
|
||||
0xba, 0xbe, 0x96, 0xc1, 0x71, 0xd2, 0x48, 0x22, 0x46, 0x76, 0xe0, 0x0e,
|
||||
0x6b, 0x2a, 0x5b, 0xd9, 0x18, 0x17, 0x47, 0x11, 0xe4, 0xe3, 0x60, 0xeb,
|
||||
0xf5, 0xa7, 0x49, 0x78, 0xef, 0xe7, 0xa9, 0x00, 0xa8, 0xe8, 0x08, 0xf7,
|
||||
0x02, 0xaa, 0xf9, 0xc7, 0xfb, 0x89, 0xff, 0x00, 0x7c, 0x8a, 0xe9, 0x84,
|
||||
0x2d, 0xb9, 0xc5, 0x56, 0xaf, 0x36, 0x89, 0x93, 0xc5, 0x7b, 0x22, 0x8d,
|
||||
0xef, 0x20, 0x7d, 0xa7, 0xee, 0x37, 0x53, 0x5a, 0xd1, 0x4a, 0x26, 0x8d,
|
||||
0x5d, 0x7a, 0x1a, 0xc2, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x15, 0x65,
|
||||
0x2f, 0x1e, 0x34, 0x84, 0x28, 0x50, 0x09, 0xe4, 0x01, 0xef, 0x44, 0xe1,
|
||||
0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xa6, 0xcb, 0x28, 0x86, 0x36,
|
||||
0x76, 0xe8, 0x29, 0x37, 0x56, 0x63, 0xde, 0x3c, 0x89, 0x30, 0x60, 0xa4,
|
||||
0x0e, 0x80, 0x8f, 0x7a, 0xc2, 0x30, 0xe6, 0x3a, 0xa7, 0x53, 0x91, 0x0d,
|
||||
0x96, 0xf6, 0x46, 0x05, 0xd2, 0x40, 0x9b, 0x8f, 0xdc, 0x5e, 0xa3, 0xde,
|
||||
0x96, 0x2b, 0xd9, 0x14, 0x07, 0x77, 0x0f, 0xb4, 0xfd, 0xc6, 0xeb, 0xf5,
|
||||
0xaa, 0xfe, 0x71, 0xfe, 0xe2, 0x7f, 0xdf, 0x22, 0x8f, 0x38, 0xff, 0x00,
|
||||
0x71, 0x3f, 0xef, 0x91, 0x5d, 0x7c, 0xaa, 0xd6, 0xb1, 0xc1, 0xce, 0xef,
|
||||
0x7b, 0x9b, 0xb1, 0xc8, 0x25, 0x45, 0x75, 0xe8, 0x46, 0x69, 0xd5, 0x95,
|
||||
0x1d, 0xe3, 0xa0, 0x81, 0x46, 0x02, 0x9e, 0xa0, 0x0f, 0x72, 0x2b, 0x4b,
|
||||
0x35, 0xc9, 0x28, 0xf2, 0x9d, 0xf0, 0xa9, 0xce, 0x85, 0x92, 0x41, 0x1a,
|
||||
0x33, 0xb7, 0x40, 0x32, 0x6b, 0x2a, 0x5b, 0xd9, 0x1c, 0x17, 0x47, 0x09,
|
||||
0x93, 0x8d, 0x83, 0xaf, 0xd6, 0x9d, 0x25, 0xe3, 0xbf, 0x9e, 0xa4, 0x02,
|
||||
0xa3, 0xa0, 0x23, 0xdc, 0x55, 0x5f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef,
|
||||
0x91, 0x5b, 0xc2, 0x16, 0xdc, 0xe6, 0xa9, 0x57, 0x9b, 0x44, 0xc8, 0xea,
|
||||
0x70, 0xa4, 0x88, 0x30, 0x09, 0xff, 0x00, 0xf5, 0xd3, 0x4d, 0xbb, 0x09,
|
||||
0x84, 0x59, 0x1b, 0xbd, 0x7b, 0x56, 0x95, 0xb4, 0x66, 0x18, 0x42, 0x13,
|
||||
0x92, 0x3d, 0x2a, 0xe5, 0x2b, 0x23, 0x2a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
|
||||
0xc8, 0x2a, 0x40, 0x9f, 0x20, 0x8f, 0xff, 0x00, 0x5d, 0x6a, 0xe6, 0xa3,
|
||||
0xb9, 0x8c, 0xcf, 0x09, 0x40, 0x40, 0x27, 0xd6, 0xb1, 0x83, 0xe5, 0x3a,
|
||||
0x6a, 0x47, 0x99, 0x5c, 0xc7, 0xa2, 0xa5, 0x5b, 0x76, 0x69, 0x8c, 0x59,
|
||||
0x1b, 0xbf, 0x4a, 0x3e, 0xce, 0xde, 0x7f, 0x95, 0x91, 0xbb, 0xd7, 0xb5,
|
||||
0x74, 0xdd, 0x1c, 0x3c, 0xac, 0x7a, 0xa9, 0x2d, 0x6f, 0x80, 0x7f, 0xcb,
|
||||
0x1a, 0xd6, 0xa8, 0x6d, 0xe3, 0x30, 0xc2, 0xa8, 0x48, 0x24, 0x77, 0x15,
|
||||
0x26, 0x6b, 0x9a, 0x6f, 0x99, 0x9d, 0xf4, 0xe3, 0xca, 0x8c, 0xb6, 0x52,
|
||||
0x1a, 0xe3, 0x20, 0xff, 0x00, 0x96, 0x15, 0x5e, 0xb6, 0x2e, 0x23, 0x33,
|
||||
0x44, 0xc8, 0x08, 0x04, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
|
||||
0x7a, 0xf6, 0xad, 0xa1, 0x24, 0xd1, 0xcb, 0x52, 0x0e, 0x2d, 0x58, 0x8a,
|
||||
0xa7, 0x0a, 0x48, 0x83, 0x00, 0x9f, 0xff, 0x00, 0x5d, 0x34, 0xdb, 0xb2,
|
||||
0xcc, 0x22, 0xc8, 0xdd, 0xeb, 0xda, 0xb4, 0xad, 0xa3, 0x30, 0xc2, 0xaa,
|
||||
0x4e, 0x48, 0xf4, 0xa2, 0x52, 0xb2, 0x0a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
|
||||
0x29, 0xa4, 0xd1, 0x9a, 0xe5, 0xb1, 0xde, 0x3a, 0x8a, 0x6e, 0x73, 0x41,
|
||||
0x34, 0x58, 0x0e, 0x7f, 0xe2, 0x1f, 0xfc, 0x88, 0xfa, 0xe7, 0xfd, 0x7a,
|
||||
0xbf, 0xf2, 0xaf, 0x95, 0xab, 0xeb, 0x2f, 0x18, 0x58, 0x4b, 0xaa, 0xf8,
|
||||
0x57, 0x56, 0xb4, 0x80, 0x6e, 0x9a, 0x6b, 0x69, 0x15, 0x17, 0xd5, 0xb6,
|
||||
0x9c, 0x0f, 0xce, 0xbe, 0x4e, 0x65, 0x2a, 0x48, 0x20, 0x82, 0x38, 0x20,
|
||||
0xf6, 0xaf, 0xc1, 0x7c, 0x46, 0x84, 0x96, 0x32, 0x84, 0xed, 0xa3, 0x8b,
|
||||
0x5f, 0x73, 0xff, 0x00, 0x82, 0x8d, 0x20, 0x25, 0x7d, 0x5d, 0xe0, 0x5f,
|
||||
0xf9, 0x12, 0xf4, 0x2f, 0xfa, 0xf2, 0x87, 0xff, 0x00, 0x40, 0x15, 0xf2,
|
||||
0x9a, 0x23, 0x48, 0xea, 0x88, 0xa5, 0x9d, 0x8e, 0x02, 0x81, 0x92, 0x4d,
|
||||
0x7d, 0x69, 0xe1, 0x8b, 0x19, 0x34, 0xbf, 0x0d, 0xe9, 0x76, 0x73, 0x71,
|
||||
0x2c, 0x16, 0xd1, 0xc6, 0xe3, 0xd0, 0x85, 0x00, 0xd5, 0x78, 0x73, 0x09,
|
||||
0x3c, 0x56, 0x22, 0x76, 0xd1, 0x45, 0x2f, 0xc7, 0xfe, 0x00, 0x4c, 0xd0,
|
||||
0xba, 0xff, 0x00, 0x8f, 0x69, 0xbf, 0xdc, 0x3f, 0xca, 0xbe, 0x39, 0xaf,
|
||||
0xb1, 0xe5, 0x5f, 0x32, 0x27, 0x4c, 0xe3, 0x72, 0x91, 0x9a, 0xf9, 0x03,
|
||||
0x50, 0xb1, 0x9b, 0x4c, 0xbe, 0xb8, 0xb4, 0x9d, 0x0a, 0x4d, 0x04, 0x86,
|
||||
0x37, 0x53, 0xd8, 0x83, 0x8a, 0xed, 0xf1, 0x22, 0x12, 0xff, 0x00, 0x65,
|
||||
0x9d, 0xb4, 0xf7, 0xd7, 0xfe, 0x92, 0x10, 0x2b, 0xd7, 0xd2, 0x5f, 0x05,
|
||||
0xbf, 0xe4, 0x9f, 0x58, 0xff, 0x00, 0xd7, 0x49, 0x7f, 0xf4, 0x33, 0x5f,
|
||||
0x36, 0xd7, 0xd3, 0x9f, 0x0a, 0x74, 0xe9, 0xb4, 0xbf, 0x01, 0xe9, 0x91,
|
||||
0x4e, 0xa5, 0x24, 0x75, 0x69, 0x76, 0x9e, 0xa0, 0x33, 0x12, 0x3f, 0x42,
|
||||
0x2b, 0xc3, 0xf0, 0xf6, 0x12, 0x96, 0x69, 0x52, 0x49, 0x68, 0xa0, 0xff,
|
||||
0x00, 0x19, 0x44, 0x72, 0xd8, 0xeb, 0xe8, 0xa6, 0xe6, 0x8c, 0xd7, 0xf4,
|
||||
0x3d, 0x8c, 0x87, 0x51, 0x4d, 0xcd, 0x19, 0xa2, 0xc0, 0x65, 0xb2, 0x90,
|
||||
0xd7, 0x19, 0x04, 0x7f, 0xfb, 0x42, 0xab, 0xd6, 0xc5, 0xc4, 0x66, 0x68,
|
||||
0x59, 0x07, 0x04, 0xfa, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
|
||||
0x7a, 0xf6, 0xae, 0xa8, 0x4a, 0xe8, 0xe0, 0xa9, 0x07, 0x16, 0xac, 0x45,
|
||||
0x53, 0x85, 0x24, 0x41, 0x80, 0x4f, 0xff, 0x00, 0xae, 0x9a, 0x6d, 0xd9,
|
||||
0x66, 0x11, 0x64, 0x6e, 0xf5, 0xed, 0x5a, 0x76, 0xd1, 0x98, 0x21, 0x0a,
|
||||
0x48, 0x27, 0xda, 0x89, 0x4a, 0xc8, 0x29, 0xc1, 0xc9, 0xb4, 0xc9, 0xab,
|
||||
0x20, 0xa9, 0x02, 0x7c, 0x82, 0x3f, 0xfd, 0x75, 0xab, 0x9a, 0x8a, 0xe6,
|
||||
0x33, 0x34, 0x45, 0x41, 0xc1, 0xf7, 0xac, 0x60, 0xf9, 0x4e, 0x9a, 0x91,
|
||||
0xe6, 0x46, 0x45, 0x15, 0x28, 0xb7, 0x66, 0x98, 0xc5, 0x91, 0xb8, 0x77,
|
||||
0xed, 0x47, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37, 0x7a, 0xf6, 0xae, 0x9b,
|
||||
0xa3, 0x87, 0x95, 0x8f, 0x55, 0x25, 0xad, 0xf0, 0x0f, 0xf9, 0x63, 0x5a,
|
||||
0xd5, 0x0d, 0xba, 0x18, 0x61, 0x54, 0x24, 0x12, 0x3d, 0x2a, 0x4c, 0xd7,
|
||||
0x34, 0xdf, 0x33, 0x3b, 0xe9, 0xc7, 0x95, 0x19, 0x6c, 0xa4, 0x35, 0xc6,
|
||||
0x41, 0xff, 0x00, 0x2c, 0x2a, 0xbd, 0x6c, 0x5c, 0x46, 0x66, 0x85, 0x90,
|
||||
0x1c, 0x13, 0xeb, 0x59, 0x9f, 0x67, 0x6f, 0x3f, 0xca, 0xc8, 0xdd, 0xfa,
|
||||
0x56, 0xd0, 0x92, 0x68, 0xe5, 0xa9, 0x06, 0x9a, 0xb1, 0xa0, 0xd6, 0xc1,
|
||||
0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa, 0x6a, 0x28, 0xae, 0x76, 0xdb, 0x3a,
|
||||
0xd2, 0xb6, 0xc1, 0x45, 0x14, 0x52, 0x19, 0x0a, 0xdb, 0x05, 0xb8, 0x32,
|
||||
0xe4, 0xe4, 0xf6, 0xa3, 0xec, 0xc3, 0xed, 0x1e, 0x6e, 0x4e, 0x7d, 0x2a,
|
||||
0x6a, 0x2a, 0xb9, 0x99, 0x3c, 0xa8, 0x28, 0xa2, 0x8a, 0x92, 0x82, 0xa1,
|
||||
0xfb, 0x30, 0xfb, 0x47, 0x9b, 0x93, 0x9f, 0x4a, 0x9a, 0x8a, 0x69, 0xd8,
|
||||
0x4d, 0x5f, 0x72, 0x16, 0xb6, 0x0d, 0x70, 0x25, 0xc9, 0xc8, 0xed, 0x53,
|
||||
0x51, 0x45, 0x0d, 0xb6, 0x09, 0x5b, 0x60, 0xa2, 0x8a, 0x29, 0x0c, 0x28,
|
||||
0xa2, 0x8a, 0x00, 0x2b, 0x83, 0xf1, 0x57, 0xc1, 0xdd, 0x1b, 0xc4, 0xb7,
|
||||
0xaf, 0x79, 0x1b, 0xcb, 0xa7, 0x5d, 0x48, 0x73, 0x21, 0x80, 0x02, 0x8e,
|
||||
0x7d, 0x4a, 0x9e, 0xff, 0x00, 0x42, 0x2b, 0xbc, 0xa2, 0xbc, 0xfc, 0x76,
|
||||
0x5f, 0x85, 0xcc, 0xa9, 0xfb, 0x1c, 0x5d, 0x35, 0x38, 0xf9, 0xfe, 0x8f,
|
||||
0x75, 0xf2, 0x1a, 0x6d, 0x1c, 0x3f, 0x84, 0xbe, 0x11, 0xe8, 0xde, 0x16,
|
||||
0xbb, 0x4b, 0xc2, 0xd2, 0x5f, 0xde, 0x27, 0x29, 0x24, 0xf8, 0xda, 0x87,
|
||||
0xd5, 0x54, 0x77, 0xf7, 0x39, 0xae, 0xe2, 0x8a, 0x29, 0xe0, 0xb0, 0x18,
|
||||
0x5c, 0xba, 0x97, 0xb1, 0xc2, 0x53, 0x50, 0x8f, 0x97, 0xeb, 0xd5, 0xfc,
|
||||
0xc2, 0xed, 0x85, 0x71, 0xfe, 0x31, 0xf8, 0x5f, 0xa4, 0x78, 0xc6, 0x6f,
|
||||
0xb4, 0xcd, 0xe6, 0x5a, 0x5e, 0xe3, 0x06, 0xe2, 0x0c, 0x65, 0xc7, 0x6d,
|
||||
0xc0, 0xf5, 0xfe, 0x7e, 0xf5, 0xd8, 0x51, 0x55, 0x8c, 0xc1, 0x61, 0xf1,
|
||||
0xf4, 0x9d, 0x0c, 0x54, 0x14, 0xe2, 0xfa, 0x3f, 0xeb, 0x46, 0x17, 0x68,
|
||||
0xf3, 0xbf, 0x0f, 0x7c, 0x11, 0xd1, 0x74, 0x6b, 0xc4, 0xb9, 0xb9, 0x96,
|
||||
0x5d, 0x49, 0xd0, 0xe5, 0x63, 0x94, 0x05, 0x8f, 0x3e, 0xa5, 0x47, 0x5f,
|
||||
0xc4, 0xe3, 0xda, 0xbd, 0x13, 0xa5, 0x14, 0x56, 0x38, 0x1c, 0xb7, 0x07,
|
||||
0x96, 0x41, 0xd3, 0xc1, 0xd3, 0x50, 0x4f, 0x7b, 0x75, 0xf5, 0x7b, 0xb0,
|
||||
0x6d, 0xb0, 0xa2, 0x8a, 0x2b, 0xd3, 0x10, 0x51, 0x45, 0x14, 0x00, 0x54,
|
||||
0x3f, 0x66, 0x1f, 0x68, 0xf3, 0x72, 0x73, 0xe9, 0x53, 0x51, 0x4d, 0x3b,
|
||||
0x09, 0xab, 0xee, 0x42, 0xd6, 0xc1, 0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa,
|
||||
0x6a, 0x28, 0xa1, 0xb6, 0xc1, 0x2b, 0x6c, 0x14, 0x51, 0x45, 0x21, 0x90,
|
||||
0xad, 0xb0, 0x5b, 0x83, 0x2e, 0x4e, 0x4f, 0x6a, 0x3e, 0xcc, 0x3e, 0xd1,
|
||||
0xe6, 0xe4, 0xe7, 0xd2, 0xa6, 0xa2, 0xab, 0x99, 0x93, 0xca, 0x82, 0x8a,
|
||||
0x28, 0xa9, 0x28, 0x2a, 0x1f, 0xb3, 0x0f, 0xb4, 0x79, 0xb9, 0x39, 0xf4,
|
||||
0xa9, 0xa8, 0xa6, 0x9d, 0x84, 0xd5, 0xf7, 0x3e, 0x20, 0xff, 0x00, 0x87,
|
||||
0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3,
|
||||
0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a,
|
||||
0xbe, 0x17, 0xfe, 0xc6, 0xb2, 0xff, 0x00, 0x9f, 0x64, 0xa7, 0x47, 0xa2,
|
||||
0x59, 0x31, 0xe6, 0xd9, 0x31, 0x45, 0x8e, 0x9e, 0x44, 0x7d, 0xcd, 0xff,
|
||||
0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
|
||||
0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
|
||||
0x15, 0x7c, 0x3b, 0xfd, 0x87, 0x61, 0xff, 0x00, 0x3e, 0xb1, 0xfe, 0x54,
|
||||
0xd9, 0x34, 0x6b, 0x05, 0x1c, 0x5b, 0x47, 0x9f, 0xa5, 0x16, 0x0e, 0x44,
|
||||
0x7d, 0xc9, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7,
|
||||
0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb,
|
||||
0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x2f, 0xfd, 0x8d, 0x65, 0xff, 0x00, 0x3e,
|
||||
0xc9, 0xf9, 0x53, 0xe3, 0xd1, 0x2c, 0x4f, 0x26, 0xd9, 0x31, 0xf4, 0xa2,
|
||||
0xc1, 0xc8, 0x8f, 0xb9, 0x7f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
|
||||
0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87, 0xa6, 0xf8,
|
||||
0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf, 0x87, 0x7f,
|
||||
0xb0, 0xec, 0x3f, 0xe7, 0xd6, 0x3f, 0xca, 0x99, 0x26, 0x8d, 0x62, 0x38,
|
||||
0x16, 0xc9, 0x9a, 0x2c, 0x1c, 0x88, 0xfb, 0x97, 0xfe, 0x1e, 0x9b, 0xe1,
|
||||
0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0x8f, 0xf8, 0x7a, 0x6f,
|
||||
0x85, 0xbf, 0xe8, 0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0xf8, 0x5f, 0xfb,
|
||||
0x1a, 0xcb, 0xfe, 0x7d, 0x93, 0xf2, 0xa9, 0x23, 0xd1, 0x2c, 0x48, 0xc9,
|
||||
0xb6, 0x4f, 0xca, 0x8b, 0x07, 0x22, 0x3e, 0xe4, 0xff, 0x00, 0x87, 0xa6,
|
||||
0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe,
|
||||
0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe,
|
||||
0x1d, 0xfe, 0xc3, 0xb0, 0xff, 0x00, 0x9f, 0x58, 0xff, 0x00, 0x2a, 0x64,
|
||||
0x9a, 0x35, 0x88, 0x38, 0x16, 0xc9, 0xf9, 0x51, 0x60, 0xe4, 0x47, 0xdc,
|
||||
0xbf, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
|
||||
0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff,
|
||||
0x00, 0x81, 0x51, 0x57, 0xc2, 0xff, 0x00, 0xd8, 0xd6, 0x5f, 0xf3, 0xec,
|
||||
0x9f, 0x95, 0x48, 0x9a, 0x1d, 0x89, 0x19, 0x36, 0xc9, 0xf9, 0x51, 0x60,
|
||||
0xe4, 0x47, 0xdc, 0x9f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac,
|
||||
0x7f, 0xe0, 0x54, 0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42,
|
||||
0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51, 0x57, 0xc3, 0xbf, 0xd8, 0x76, 0x1f,
|
||||
0xf3, 0xeb, 0x1f, 0xe5, 0x51, 0xbe, 0x8d, 0x63, 0x9c, 0x0b, 0x64, 0xfc,
|
||||
0xa8, 0xb0, 0x72, 0x23, 0xee, 0x6f, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8,
|
||||
0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
|
||||
0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x7f, 0xec,
|
||||
0x7b, 0x2f, 0xf9, 0xf6, 0x4f, 0xca, 0x9b, 0x2e, 0x9d, 0xa7, 0xdb, 0xed,
|
||||
0x53, 0x67, 0xe6, 0xc8, 0xc0, 0x90, 0xb1, 0xae, 0x4e, 0x3d, 0x68, 0xb0,
|
||||
0x72, 0x23, 0xee, 0xaf, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8, 0x47, 0xd6,
|
||||
0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
|
||||
0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x1f, 0x23, 0x4b, 0xd8,
|
||||
0x1b, 0xec, 0x44, 0x8d, 0xbb, 0x9b, 0x09, 0xf7, 0x06, 0x48, 0xc9, 0xe7,
|
||||
0xd8, 0xfe, 0x54, 0x3d, 0x9e, 0x9e, 0x2e, 0x04, 0x66, 0xcb, 0x60, 0x27,
|
||||
0x68, 0x72, 0xbf, 0x29, 0x3f, 0x5c, 0xd1, 0x60, 0xe4, 0x47, 0xdd, 0xdf,
|
||||
0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x54,
|
||||
0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00,
|
||||
0x81, 0x51, 0x57, 0xc1, 0x82, 0xdf, 0x4e, 0x1b, 0xb7, 0xd9, 0x98, 0x88,
|
||||
0x19, 0xda, 0xeb, 0xc9, 0xe7, 0x1c, 0x73, 0xea, 0x45, 0x4d, 0x1d, 0x9e,
|
||||
0x9a, 0x46, 0x0d, 0x91, 0x12, 0x02, 0x41, 0x8c, 0xaf, 0xcd, 0x9c, 0x67,
|
||||
0xd7, 0xd2, 0x8b, 0x07, 0x22, 0x3e, 0xed, 0xff, 0x00, 0x87, 0xa6, 0xf8,
|
||||
0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e,
|
||||
0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x16,
|
||||
0xb7, 0xd3, 0xf4, 0xeb, 0x86, 0x65, 0xfb, 0x1f, 0x96, 0xea, 0x01, 0x2b,
|
||||
0x22, 0xe0, 0xe0, 0xf7, 0xa7, 0x36, 0x8f, 0x62, 0x49, 0xc5, 0xb2, 0x62,
|
||||
0x8b, 0x07, 0x22, 0x3e, 0xe7, 0xff, 0x00, 0x87, 0xa6, 0xf8, 0x5b, 0xfe,
|
||||
0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e, 0x9b, 0xe1,
|
||||
0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x17, 0xfe, 0xc6,
|
||||
0xb2, 0x3f, 0xf2, 0xec, 0x95, 0x30, 0xd0, 0xec, 0x40, 0xff, 0x00, 0x8f,
|
||||
0x64, 0xa2, 0xc1, 0xc8, 0x8f, 0xb8, 0xbf, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
|
||||
0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87,
|
||||
0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf,
|
||||
0x87, 0x7f, 0xb1, 0x2c, 0x07, 0xfc, 0xba, 0xc7, 0xf9, 0x54, 0x27, 0x47,
|
||||
0xb2, 0x27, 0xfe, 0x3d, 0x92, 0x8b, 0x07, 0x22, 0x3e, 0xe8, 0xff, 0x00,
|
||||
0x87, 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2,
|
||||
0xa3, 0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a,
|
||||
0x8a, 0xbe, 0x17, 0x1a, 0x2d, 0x91, 0x38, 0xfb, 0x32, 0x54, 0xdf, 0xd8,
|
||||
0x76, 0x1f, 0xf3, 0xea, 0x9f, 0x95, 0x16, 0x0e, 0x44, 0x7d, 0xc5, 0xff,
|
||||
0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
|
||||
0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
|
||||
0x15, 0x7c, 0x3a, 0x74, 0x4b, 0x00, 0x33, 0xf6, 0x58, 0xff, 0x00, 0x2a,
|
||||
0x84, 0xe8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x47,
|
||||
0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15,
|
||||
0x1f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
|
||||
0x55, 0xf0, 0xc2, 0xe8, 0xb6, 0x4c, 0x40, 0xfb, 0x32, 0x54, 0xbf, 0xd8,
|
||||
0x76, 0x1f, 0xf3, 0xea, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x17, 0xfc, 0x3d,
|
||||
0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x1f, 0xf0,
|
||||
0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x55, 0xf0,
|
||||
0xe3, 0x68, 0xb6, 0x0a, 0x09, 0xfb, 0x2c, 0x7f, 0x95, 0x45, 0xfd, 0x8d,
|
||||
0x65, 0xff, 0x00, 0x3e, 0xc9, 0x45, 0x83, 0x91, 0x1f, 0x74, 0x7f, 0xc3,
|
||||
0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51,
|
||||
0x51, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe,
|
||||
0x05, 0x45, 0x5f, 0x0c, 0x26, 0x89, 0x64, 0xcd, 0xff, 0x00, 0x1e, 0xc9,
|
||||
0x52, 0xff, 0x00, 0x61, 0xd8, 0x7f, 0xcf, 0xac, 0x7f, 0x95, 0x16, 0x0e,
|
||||
0x44, 0x7d, 0xc5, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa,
|
||||
0xc7, 0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23,
|
||||
0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x38, 0xfa, 0x2d, 0x82, 0xaf, 0xfc,
|
||||
0x7a, 0xc7, 0xf9, 0x54, 0x5f, 0xd8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58,
|
||||
0x39, 0x11, 0x72, 0xa7, 0x45, 0xda, 0xb8, 0xa8, 0xe3, 0x5c, 0xb6, 0x7d,
|
||||
0x2a, 0x5a, 0xa2, 0xc2, 0xa1, 0x66, 0xdc, 0xd9, 0xa7, 0xc8, 0xd8, 0x18,
|
||||
0xf5, 0xa8, 0xa8, 0x01, 0x40, 0xc9, 0xa9, 0xd4, 0x6d, 0x18, 0xa8, 0xe2,
|
||||
0x5e, 0x73, 0x52, 0x50, 0x00, 0x4e, 0x05, 0x40, 0xc7, 0x71, 0xcd, 0x49,
|
||||
0x2b, 0x71, 0x8a, 0x8a, 0x80, 0x14, 0x0c, 0x9c, 0x54, 0xe0, 0x60, 0x62,
|
||||
0xa3, 0x89, 0x7b, 0xd4, 0x94, 0x00, 0x13, 0x80, 0x4d, 0x40, 0x4e, 0x4e,
|
||||
0x69, 0xf2, 0xb7, 0x6a, 0x8e, 0x80, 0x15, 0x46, 0xe3, 0x8a, 0x9e, 0x99,
|
||||
0x1a, 0xe0, 0x67, 0xd6, 0x9f, 0x40, 0x08, 0xc7, 0x68, 0xcd, 0x41, 0x4f,
|
||||
0x91, 0xb2, 0x71, 0xe9, 0x4c, 0xa0, 0x07, 0x22, 0xee, 0x6f, 0x6a, 0x27,
|
||||
0xb5, 0x59, 0xa4, 0x49, 0x37, 0xbc, 0x6e, 0xbc, 0x06, 0x43, 0x8c, 0x8f,
|
||||
0x43, 0xed, 0x52, 0x46, 0xb8, 0x5f, 0x73, 0x4e, 0xa0, 0x0a, 0xa6, 0xca,
|
||||
0x38, 0xa2, 0x95, 0x41, 0x6f, 0xde, 0x2e, 0xc3, 0xcf, 0x6c, 0x93, 0xff,
|
||||
0x00, 0xb3, 0x1a, 0x87, 0xec, 0x60, 0xca, 0xae, 0xd2, 0x48, 0xe1, 0x4e,
|
||||
0x42, 0x12, 0x36, 0x83, 0xf9, 0x55, 0xa9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d,
|
||||
0x00, 0x57, 0x8b, 0x49, 0xb7, 0x0c, 0xfb, 0x53, 0xcb, 0x0c, 0x00, 0x21,
|
||||
0x38, 0xe8, 0x72, 0x0f, 0xd6, 0xa6, 0x5d, 0x39, 0x17, 0x90, 0xf2, 0x79,
|
||||
0x99, 0x2c, 0x64, 0x27, 0x2c, 0x4e, 0xdc, 0x7e, 0x82, 0xac, 0xa2, 0xed,
|
||||
0x5a, 0x5a, 0x00, 0xad, 0x1d, 0xaa, 0xdb, 0x16, 0x6f, 0x31, 0xe5, 0x91,
|
||||
0xc0, 0x05, 0xe4, 0x39, 0x38, 0x1d, 0xbf, 0x5a, 0x5a, 0x73, 0xb6, 0xe6,
|
||||
0xa6, 0xf5, 0xa0, 0x07, 0xc4, 0xb9, 0x39, 0xf4, 0xa9, 0x69, 0x14, 0x6d,
|
||||
0x18, 0xa5, 0xe9, 0x40, 0x0c, 0x95, 0xb0, 0x31, 0x51, 0x52, 0xb1, 0xdc,
|
||||
0x49, 0xa0, 0x0c, 0x9c, 0x50, 0x03, 0xe2, 0x5e, 0xf5, 0x25, 0x00, 0x60,
|
||||
0x62, 0x82, 0x70, 0x33, 0x40, 0x11, 0xca, 0xdd, 0xaa, 0x3a, 0x52, 0x72,
|
||||
0x73, 0x42, 0x8d, 0xc4, 0x0a, 0x00, 0x92, 0x25, 0xc0, 0xcd, 0x3e, 0x8e,
|
||||
0x94, 0x8c, 0x76, 0x82, 0x68, 0x02, 0x39, 0x5b, 0x27, 0x1e, 0x94, 0xca,
|
||||
0x3a, 0xd3, 0x91, 0x77, 0x35, 0x00, 0x49, 0x1a, 0xe1, 0x7d, 0xcd, 0x3a,
|
||||
0x8a, 0x47, 0x6d, 0xab, 0x40, 0x11, 0xc8, 0xd9, 0x6f, 0x61, 0x4c, 0xa2,
|
||||
0x9d, 0x1a, 0xee, 0x6f, 0x61, 0x40, 0x1f, 0xff, 0xd9
|
||||
};
|
@ -1,433 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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 "FakeCamera"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include "FakeCamera.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// TODO: All this rgb to yuv should probably be in a util class.
|
||||
|
||||
// TODO: I think something is wrong in this class because the shadow is kBlue
|
||||
// and the square color should alternate between kRed and kGreen. However on the
|
||||
// emulator screen these are all shades of gray. Y seems ok but the U and V are
|
||||
// probably not.
|
||||
|
||||
static int tables_initialized = 0;
|
||||
uint8_t *gYTable, *gCbTable, *gCrTable;
|
||||
|
||||
static int
|
||||
clamp(int x)
|
||||
{
|
||||
if (x > 255) return 255;
|
||||
if (x < 0) return 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* the equation used by the video code to translate YUV to RGB looks like this
|
||||
*
|
||||
* Y = (Y0 - 16)*k0
|
||||
* Cb = Cb0 - 128
|
||||
* Cr = Cr0 - 128
|
||||
*
|
||||
* G = ( Y - k1*Cr - k2*Cb )
|
||||
* R = ( Y + k3*Cr )
|
||||
* B = ( Y + k4*Cb )
|
||||
*
|
||||
*/
|
||||
|
||||
static const double k0 = 1.164;
|
||||
static const double k1 = 0.813;
|
||||
static const double k2 = 0.391;
|
||||
static const double k3 = 1.596;
|
||||
static const double k4 = 2.018;
|
||||
|
||||
/* let's try to extract the value of Y
|
||||
*
|
||||
* G + k1/k3*R + k2/k4*B = Y*( 1 + k1/k3 + k2/k4 )
|
||||
*
|
||||
* Y = ( G + k1/k3*R + k2/k4*B ) / (1 + k1/k3 + k2/k4)
|
||||
* Y0 = ( G0 + k1/k3*R0 + k2/k4*B0 ) / ((1 + k1/k3 + k2/k4)*k0) + 16
|
||||
*
|
||||
* let define:
|
||||
* kYr = k1/k3
|
||||
* kYb = k2/k4
|
||||
* kYy = k0 * ( 1 + kYr + kYb )
|
||||
*
|
||||
* we have:
|
||||
* Y = ( G + kYr*R + kYb*B )
|
||||
* Y0 = clamp[ Y/kYy + 16 ]
|
||||
*/
|
||||
|
||||
static const double kYr = k1/k3;
|
||||
static const double kYb = k2/k4;
|
||||
static const double kYy = k0*( 1. + kYr + kYb );
|
||||
|
||||
static void
|
||||
initYtab( void )
|
||||
{
|
||||
const int imax = (int)( (kYr + kYb)*(31 << 2) + (61 << 3) + 0.1 );
|
||||
int i;
|
||||
|
||||
gYTable = (uint8_t *)malloc(imax);
|
||||
|
||||
for(i=0; i<imax; i++) {
|
||||
int x = (int)(i/kYy + 16.5);
|
||||
if (x < 16) x = 16;
|
||||
else if (x > 235) x = 235;
|
||||
gYTable[i] = (uint8_t) x;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the source is RGB565, so adjust for 8-bit range of input values:
|
||||
*
|
||||
* G = (pixels >> 3) & 0xFC;
|
||||
* R = (pixels >> 8) & 0xF8;
|
||||
* B = (pixels & 0x1f) << 3;
|
||||
*
|
||||
* R2 = (pixels >> 11) R = R2*8
|
||||
* B2 = (pixels & 0x1f) B = B2*8
|
||||
*
|
||||
* kYr*R = kYr2*R2 => kYr2 = kYr*8
|
||||
* kYb*B = kYb2*B2 => kYb2 = kYb*8
|
||||
*
|
||||
* we want to use integer multiplications:
|
||||
*
|
||||
* SHIFT1 = 9
|
||||
*
|
||||
* (ALPHA*R2) >> SHIFT1 == R*kYr => ALPHA = kYr*8*(1 << SHIFT1)
|
||||
*
|
||||
* ALPHA = kYr*(1 << (SHIFT1+3))
|
||||
* BETA = kYb*(1 << (SHIFT1+3))
|
||||
*/
|
||||
|
||||
static const int SHIFT1 = 9;
|
||||
static const int ALPHA = (int)( kYr*(1 << (SHIFT1+3)) + 0.5 );
|
||||
static const int BETA = (int)( kYb*(1 << (SHIFT1+3)) + 0.5 );
|
||||
|
||||
/*
|
||||
* now let's try to get the values of Cb and Cr
|
||||
*
|
||||
* R-B = (k3*Cr - k4*Cb)
|
||||
*
|
||||
* k3*Cr = k4*Cb + (R-B)
|
||||
* k4*Cb = k3*Cr - (R-B)
|
||||
*
|
||||
* R-G = (k1+k3)*Cr + k2*Cb
|
||||
* = (k1+k3)*Cr + k2/k4*(k3*Cr - (R-B)/k0)
|
||||
* = (k1 + k3 + k2*k3/k4)*Cr - k2/k4*(R-B)
|
||||
*
|
||||
* kRr*Cr = (R-G) + kYb*(R-B)
|
||||
*
|
||||
* Cr = ((R-G) + kYb*(R-B))/kRr
|
||||
* Cr0 = clamp(Cr + 128)
|
||||
*/
|
||||
|
||||
static const double kRr = (k1 + k3 + k2*k3/k4);
|
||||
|
||||
static void
|
||||
initCrtab( void )
|
||||
{
|
||||
uint8_t *pTable;
|
||||
int i;
|
||||
|
||||
gCrTable = (uint8_t *)malloc(768*2);
|
||||
|
||||
pTable = gCrTable + 384;
|
||||
for(i=-384; i<384; i++)
|
||||
pTable[i] = (uint8_t) clamp( i/kRr + 128.5 );
|
||||
}
|
||||
|
||||
/*
|
||||
* B-G = (k2 + k4)*Cb + k1*Cr
|
||||
* = (k2 + k4)*Cb + k1/k3*(k4*Cb + (R-B))
|
||||
* = (k2 + k4 + k1*k4/k3)*Cb + k1/k3*(R-B)
|
||||
*
|
||||
* kBb*Cb = (B-G) - kYr*(R-B)
|
||||
*
|
||||
* Cb = ((B-G) - kYr*(R-B))/kBb
|
||||
* Cb0 = clamp(Cb + 128)
|
||||
*
|
||||
*/
|
||||
|
||||
static const double kBb = (k2 + k4 + k1*k4/k3);
|
||||
|
||||
static void
|
||||
initCbtab( void )
|
||||
{
|
||||
uint8_t *pTable;
|
||||
int i;
|
||||
|
||||
gCbTable = (uint8_t *)malloc(768*2);
|
||||
|
||||
pTable = gCbTable + 384;
|
||||
for(i=-384; i<384; i++)
|
||||
pTable[i] = (uint8_t) clamp( i/kBb + 128.5 );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHIFT2 = 16
|
||||
*
|
||||
* DELTA = kYb*(1 << SHIFT2)
|
||||
* GAMMA = kYr*(1 << SHIFT2)
|
||||
*/
|
||||
|
||||
static const int SHIFT2 = 16;
|
||||
static const int DELTA = kYb*(1 << SHIFT2);
|
||||
static const int GAMMA = kYr*(1 << SHIFT2);
|
||||
|
||||
int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420,
|
||||
uint32_t *param, uint8_t *table[])
|
||||
{
|
||||
uint16_t *inputRGB = (uint16_t*)rgb16;
|
||||
uint8_t *outYUV = yuv420;
|
||||
int32_t width_dst = param[0];
|
||||
int32_t height_dst = param[1];
|
||||
int32_t pitch_dst = param[2];
|
||||
int32_t mheight_dst = param[3];
|
||||
int32_t pitch_src = param[4];
|
||||
uint8_t *y_tab = table[0];
|
||||
uint8_t *cb_tab = table[1];
|
||||
uint8_t *cr_tab = table[2];
|
||||
|
||||
int32_t size16 = pitch_dst*mheight_dst;
|
||||
int32_t i,j,count;
|
||||
int32_t ilimit,jlimit;
|
||||
uint8_t *tempY,*tempU,*tempV;
|
||||
uint16_t pixels;
|
||||
int tmp;
|
||||
uint32_t temp;
|
||||
|
||||
tempY = outYUV;
|
||||
tempU = outYUV + (height_dst * pitch_dst);
|
||||
tempV = tempU + 1;
|
||||
|
||||
jlimit = height_dst;
|
||||
ilimit = width_dst;
|
||||
|
||||
for(j=0; j<jlimit; j+=1)
|
||||
{
|
||||
for (i=0; i<ilimit; i+=2)
|
||||
{
|
||||
int32_t G_ds = 0, B_ds = 0, R_ds = 0;
|
||||
uint8_t y0, y1, u, v;
|
||||
|
||||
pixels = inputRGB[i];
|
||||
temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
|
||||
y0 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
|
||||
|
||||
G_ds += (pixels>>1) & 0x03E0;
|
||||
B_ds += (pixels<<5) & 0x03E0;
|
||||
R_ds += (pixels>>6) & 0x03E0;
|
||||
|
||||
pixels = inputRGB[i+1];
|
||||
temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
|
||||
y1 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
|
||||
|
||||
G_ds += (pixels>>1) & 0x03E0;
|
||||
B_ds += (pixels<<5) & 0x03E0;
|
||||
R_ds += (pixels>>6) & 0x03E0;
|
||||
|
||||
R_ds >>= 1;
|
||||
B_ds >>= 1;
|
||||
G_ds >>= 1;
|
||||
|
||||
tmp = R_ds - B_ds;
|
||||
|
||||
u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
|
||||
v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
|
||||
|
||||
tempY[0] = y0;
|
||||
tempY[1] = y1;
|
||||
tempY += 2;
|
||||
|
||||
if ((j&1) == 0) {
|
||||
tempU[0] = u;
|
||||
tempV[0] = v;
|
||||
tempU += 2;
|
||||
tempV += 2;
|
||||
}
|
||||
}
|
||||
|
||||
inputRGB += pitch_src;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height)
|
||||
{
|
||||
if (!tables_initialized) {
|
||||
initYtab();
|
||||
initCrtab();
|
||||
initCbtab();
|
||||
tables_initialized = 1;
|
||||
}
|
||||
|
||||
uint32_t param[6];
|
||||
param[0] = (uint32_t) width;
|
||||
param[1] = (uint32_t) height;
|
||||
param[2] = (uint32_t) width;
|
||||
param[3] = (uint32_t) height;
|
||||
param[4] = (uint32_t) width;
|
||||
param[5] = (uint32_t) 0;
|
||||
|
||||
uint8_t *table[3];
|
||||
table[0] = gYTable;
|
||||
table[1] = gCbTable + 384;
|
||||
table[2] = gCrTable + 384;
|
||||
|
||||
ccrgb16toyuv_wo_colorkey(rgb, yuv, param, table);
|
||||
}
|
||||
|
||||
const int FakeCamera::kRed;
|
||||
const int FakeCamera::kGreen;
|
||||
const int FakeCamera::kBlue;
|
||||
|
||||
FakeCamera::FakeCamera(int width, int height)
|
||||
: mTmpRgb16Buffer(0)
|
||||
{
|
||||
setSize(width, height);
|
||||
}
|
||||
|
||||
FakeCamera::~FakeCamera()
|
||||
{
|
||||
delete[] mTmpRgb16Buffer;
|
||||
}
|
||||
|
||||
void FakeCamera::setSize(int width, int height)
|
||||
{
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mCounter = 0;
|
||||
mCheckX = 0;
|
||||
mCheckY = 0;
|
||||
|
||||
// This will cause it to be reallocated on the next call
|
||||
// to getNextFrameAsYuv420().
|
||||
delete[] mTmpRgb16Buffer;
|
||||
mTmpRgb16Buffer = 0;
|
||||
}
|
||||
|
||||
void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer)
|
||||
{
|
||||
int size = mWidth / 10;
|
||||
|
||||
drawCheckerboard(buffer, size);
|
||||
|
||||
int x = ((mCounter*3)&255);
|
||||
if(x>128) x = 255 - x;
|
||||
int y = ((mCounter*5)&255);
|
||||
if(y>128) y = 255 - y;
|
||||
|
||||
drawSquare(buffer, x*size/32, y*size/32, (size*5)>>1, (mCounter&0x100)?kRed:kGreen, kBlue);
|
||||
|
||||
mCounter++;
|
||||
}
|
||||
|
||||
void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer)
|
||||
{
|
||||
if (mTmpRgb16Buffer == 0)
|
||||
mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
|
||||
|
||||
getNextFrameAsRgb565(mTmpRgb16Buffer);
|
||||
convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight);
|
||||
}
|
||||
|
||||
void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow)
|
||||
{
|
||||
int square_xstop, square_ystop, shadow_xstop, shadow_ystop;
|
||||
|
||||
square_xstop = min(mWidth, x+size);
|
||||
square_ystop = min(mHeight, y+size);
|
||||
shadow_xstop = min(mWidth, x+size+(size/4));
|
||||
shadow_ystop = min(mHeight, y+size+(size/4));
|
||||
|
||||
// Do the shadow.
|
||||
uint16_t *sh = &dst[(y+(size/4))*mWidth];
|
||||
for (int j = y + (size/4); j < shadow_ystop; j++) {
|
||||
for (int i = x + (size/4); i < shadow_xstop; i++) {
|
||||
sh[i] &= shadow;
|
||||
}
|
||||
sh += mWidth;
|
||||
}
|
||||
|
||||
// Draw the square.
|
||||
uint16_t *sq = &dst[y*mWidth];
|
||||
for (int j = y; j < square_ystop; j++) {
|
||||
for (int i = x; i < square_xstop; i++) {
|
||||
sq[i] = color;
|
||||
}
|
||||
sq += mWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void FakeCamera::drawCheckerboard(uint16_t *dst, int size)
|
||||
{
|
||||
bool black = true;
|
||||
|
||||
if((mCheckX/size)&1)
|
||||
black = false;
|
||||
if((mCheckY/size)&1)
|
||||
black = !black;
|
||||
|
||||
int county = mCheckY%size;
|
||||
int checkxremainder = mCheckX%size;
|
||||
|
||||
for(int y=0;y<mHeight;y++) {
|
||||
int countx = checkxremainder;
|
||||
bool current = black;
|
||||
for(int x=0;x<mWidth;x++) {
|
||||
dst[y*mWidth+x] = current?0:0xffff;
|
||||
if(countx++ >= size) {
|
||||
countx=0;
|
||||
current = !current;
|
||||
}
|
||||
}
|
||||
if(county++ >= size) {
|
||||
county=0;
|
||||
black = !black;
|
||||
}
|
||||
}
|
||||
mCheckX += 3;
|
||||
mCheckY++;
|
||||
}
|
||||
|
||||
|
||||
void FakeCamera::dump(int fd) const
|
||||
{
|
||||
const size_t SIZE = 256;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
|
||||
result.append(buffer);
|
||||
::write(fd, result.string(), result.size());
|
||||
}
|
||||
|
||||
|
||||
}; // namespace android
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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_HARDWARE_FAKECAMERA_H
|
||||
#define ANDROID_HARDWARE_FAKECAMERA_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* FakeCamera is used in the CameraHardwareStub to provide a fake video feed
|
||||
* when the system does not have a camera in hardware.
|
||||
* The fake video is a moving black and white checkerboard background with a
|
||||
* bouncing gray square in the foreground.
|
||||
* This class is not thread-safe.
|
||||
*
|
||||
* TODO: Since the major methods provides a raw/uncompressed video feed, rename
|
||||
* this class to RawVideoSource.
|
||||
*/
|
||||
|
||||
class FakeCamera {
|
||||
public:
|
||||
FakeCamera(int width, int height);
|
||||
~FakeCamera();
|
||||
|
||||
void setSize(int width, int height);
|
||||
void getNextFrameAsYuv420(uint8_t *buffer);
|
||||
// Write to the fd a string representing the current state.
|
||||
void dump(int fd) const;
|
||||
|
||||
private:
|
||||
// TODO: remove the uint16_t buffer param everywhere since it is a field of
|
||||
// this class.
|
||||
void getNextFrameAsRgb565(uint16_t *buffer);
|
||||
|
||||
void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
|
||||
void drawCheckerboard(uint16_t *buffer, int size);
|
||||
|
||||
static const int kRed = 0xf800;
|
||||
static const int kGreen = 0x07c0;
|
||||
static const int kBlue = 0x003e;
|
||||
|
||||
int mWidth, mHeight;
|
||||
int mCounter;
|
||||
int mCheckX, mCheckY;
|
||||
uint16_t *mTmpRgb16Buffer;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_FAKECAMERA_H
|
@ -1,26 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= CameraServiceTest.cpp
|
||||
|
||||
LOCAL_MODULE:= CameraServiceTest
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
frameworks/base/libs
|
||||
|
||||
LOCAL_CFLAGS :=
|
||||
|
||||
LOCAL_SHARED_LIBRARIES += \
|
||||
libbinder \
|
||||
libcutils \
|
||||
libutils \
|
||||
libui \
|
||||
libcamera_client \
|
||||
libsurfaceflinger_client
|
||||
|
||||
# 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.
|
||||
#include $(BUILD_EXECUTABLE)
|
@ -1,919 +0,0 @@
|
||||
#define LOG_TAG "CameraServiceTest"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <surfaceflinger/ISurface.h>
|
||||
#include <camera/Camera.h>
|
||||
#include <camera/CameraParameters.h>
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#include <camera/ICamera.h>
|
||||
#include <camera/ICameraClient.h>
|
||||
#include <camera/ICameraService.h>
|
||||
#include <ui/Overlay.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
//
|
||||
// Assertion and Logging utilities
|
||||
//
|
||||
#define INFO(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
LOGD(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
void assert_fail(const char *file, int line, const char *func, const char *expr) {
|
||||
INFO("assertion failed at file %s, line %d, function %s:",
|
||||
file, line, func);
|
||||
INFO("%s", expr);
|
||||
abort();
|
||||
}
|
||||
|
||||
void assert_eq_fail(const char *file, int line, const char *func,
|
||||
const char *expr, int actual) {
|
||||
INFO("assertion failed at file %s, line %d, function %s:",
|
||||
file, line, func);
|
||||
INFO("(expected) %s != (actual) %d", expr, actual);
|
||||
abort();
|
||||
}
|
||||
|
||||
#define ASSERT(e) \
|
||||
do { \
|
||||
if (!(e)) \
|
||||
assert_fail(__FILE__, __LINE__, __func__, #e); \
|
||||
} while(0)
|
||||
|
||||
#define ASSERT_EQ(expected, actual) \
|
||||
do { \
|
||||
int _x = (actual); \
|
||||
if (_x != (expected)) \
|
||||
assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
|
||||
} while(0)
|
||||
|
||||
//
|
||||
// Holder service for pass objects between processes.
|
||||
//
|
||||
class IHolder : public IInterface {
|
||||
protected:
|
||||
enum {
|
||||
HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
|
||||
HOLDER_GET,
|
||||
HOLDER_CLEAR
|
||||
};
|
||||
public:
|
||||
DECLARE_META_INTERFACE(Holder);
|
||||
|
||||
virtual void put(sp<IBinder> obj) = 0;
|
||||
virtual sp<IBinder> get() = 0;
|
||||
virtual void clear() = 0;
|
||||
};
|
||||
|
||||
class BnHolder : public BnInterface<IHolder> {
|
||||
virtual status_t onTransact(uint32_t code,
|
||||
const Parcel& data,
|
||||
Parcel* reply,
|
||||
uint32_t flags = 0);
|
||||
};
|
||||
|
||||
class BpHolder : public BpInterface<IHolder> {
|
||||
public:
|
||||
BpHolder(const sp<IBinder>& impl)
|
||||
: BpInterface<IHolder>(impl) {
|
||||
}
|
||||
|
||||
virtual void put(sp<IBinder> obj) {
|
||||
Parcel data, reply;
|
||||
data.writeStrongBinder(obj);
|
||||
remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
|
||||
}
|
||||
|
||||
virtual sp<IBinder> get() {
|
||||
Parcel data, reply;
|
||||
remote()->transact(HOLDER_GET, data, &reply);
|
||||
return reply.readStrongBinder();
|
||||
}
|
||||
|
||||
virtual void clear() {
|
||||
Parcel data, reply;
|
||||
remote()->transact(HOLDER_CLEAR, data, &reply);
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
|
||||
|
||||
status_t BnHolder::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
|
||||
switch(code) {
|
||||
case HOLDER_PUT: {
|
||||
put(data.readStrongBinder());
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case HOLDER_GET: {
|
||||
reply->writeStrongBinder(get());
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case HOLDER_CLEAR: {
|
||||
clear();
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
}
|
||||
|
||||
class HolderService : public BnHolder {
|
||||
virtual void put(sp<IBinder> obj) {
|
||||
mObj = obj;
|
||||
}
|
||||
virtual sp<IBinder> get() {
|
||||
return mObj;
|
||||
}
|
||||
virtual void clear() {
|
||||
mObj.clear();
|
||||
}
|
||||
private:
|
||||
sp<IBinder> mObj;
|
||||
};
|
||||
|
||||
//
|
||||
// A mock CameraClient
|
||||
//
|
||||
class MCameraClient : public BnCameraClient {
|
||||
public:
|
||||
virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
|
||||
virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
|
||||
virtual void dataCallbackTimestamp(nsecs_t timestamp,
|
||||
int32_t msgType, const sp<IMemory>& data);
|
||||
|
||||
// new functions
|
||||
void clearStat();
|
||||
enum OP { EQ, GE, LE, GT, LT };
|
||||
void assertNotify(int32_t msgType, OP op, int count);
|
||||
void assertData(int32_t msgType, OP op, int count);
|
||||
void waitNotify(int32_t msgType, OP op, int count);
|
||||
void waitData(int32_t msgType, OP op, int count);
|
||||
void assertDataSize(int32_t msgType, OP op, int dataSize);
|
||||
|
||||
void setReleaser(ICamera *releaser) {
|
||||
mReleaser = releaser;
|
||||
}
|
||||
private:
|
||||
Mutex mLock;
|
||||
Condition mCond;
|
||||
DefaultKeyedVector<int32_t, int> mNotifyCount;
|
||||
DefaultKeyedVector<int32_t, int> mDataCount;
|
||||
DefaultKeyedVector<int32_t, int> mDataSize;
|
||||
bool test(OP op, int v1, int v2);
|
||||
void assertTest(OP op, int v1, int v2);
|
||||
|
||||
ICamera *mReleaser;
|
||||
};
|
||||
|
||||
void MCameraClient::clearStat() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mNotifyCount.clear();
|
||||
mDataCount.clear();
|
||||
mDataSize.clear();
|
||||
}
|
||||
|
||||
bool MCameraClient::test(OP op, int v1, int v2) {
|
||||
switch (op) {
|
||||
case EQ: return v1 == v2;
|
||||
case GT: return v1 > v2;
|
||||
case LT: return v1 < v2;
|
||||
case GE: return v1 >= v2;
|
||||
case LE: return v1 <= v2;
|
||||
default: ASSERT(0); break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MCameraClient::assertTest(OP op, int v1, int v2) {
|
||||
if (!test(op, v1, v2)) {
|
||||
LOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
int v = mNotifyCount.valueFor(msgType);
|
||||
assertTest(op, v, count);
|
||||
}
|
||||
|
||||
void MCameraClient::assertData(int32_t msgType, OP op, int count) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
int v = mDataCount.valueFor(msgType);
|
||||
assertTest(op, v, count);
|
||||
}
|
||||
|
||||
void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
int v = mDataSize.valueFor(msgType);
|
||||
assertTest(op, v, dataSize);
|
||||
}
|
||||
|
||||
void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
|
||||
INFO("%s", __func__);
|
||||
Mutex::Autolock _l(mLock);
|
||||
ssize_t i = mNotifyCount.indexOfKey(msgType);
|
||||
if (i < 0) {
|
||||
mNotifyCount.add(msgType, 1);
|
||||
} else {
|
||||
++mNotifyCount.editValueAt(i);
|
||||
}
|
||||
mCond.signal();
|
||||
}
|
||||
|
||||
void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
|
||||
INFO("%s", __func__);
|
||||
int dataSize = data->size();
|
||||
INFO("data type = %d, size = %d", msgType, dataSize);
|
||||
Mutex::Autolock _l(mLock);
|
||||
ssize_t i = mDataCount.indexOfKey(msgType);
|
||||
if (i < 0) {
|
||||
mDataCount.add(msgType, 1);
|
||||
mDataSize.add(msgType, dataSize);
|
||||
} else {
|
||||
++mDataCount.editValueAt(i);
|
||||
mDataSize.editValueAt(i) = dataSize;
|
||||
}
|
||||
mCond.signal();
|
||||
|
||||
if (msgType == CAMERA_MSG_VIDEO_FRAME) {
|
||||
ASSERT(mReleaser != NULL);
|
||||
mReleaser->releaseRecordingFrame(data);
|
||||
}
|
||||
}
|
||||
|
||||
void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
|
||||
const sp<IMemory>& data) {
|
||||
dataCallback(msgType, data);
|
||||
}
|
||||
|
||||
void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
|
||||
INFO("waitNotify: %d, %d, %d", msgType, op, count);
|
||||
Mutex::Autolock _l(mLock);
|
||||
while (true) {
|
||||
int v = mNotifyCount.valueFor(msgType);
|
||||
if (test(op, v, count)) {
|
||||
break;
|
||||
}
|
||||
mCond.wait(mLock);
|
||||
}
|
||||
}
|
||||
|
||||
void MCameraClient::waitData(int32_t msgType, OP op, int count) {
|
||||
INFO("waitData: %d, %d, %d", msgType, op, count);
|
||||
Mutex::Autolock _l(mLock);
|
||||
while (true) {
|
||||
int v = mDataCount.valueFor(msgType);
|
||||
if (test(op, v, count)) {
|
||||
break;
|
||||
}
|
||||
mCond.wait(mLock);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// A mock Surface
|
||||
//
|
||||
class MSurface : public BnSurface {
|
||||
public:
|
||||
virtual status_t registerBuffers(const BufferHeap& buffers);
|
||||
virtual void postBuffer(ssize_t offset);
|
||||
virtual void unregisterBuffers();
|
||||
virtual sp<OverlayRef> createOverlay(
|
||||
uint32_t w, uint32_t h, int32_t format, int32_t orientation);
|
||||
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
|
||||
virtual status_t setBufferCount(int bufferCount);
|
||||
|
||||
// new functions
|
||||
void clearStat();
|
||||
void waitUntil(int c0, int c1, int c2);
|
||||
|
||||
private:
|
||||
// check callback count
|
||||
Condition mCond;
|
||||
Mutex mLock;
|
||||
int registerBuffersCount;
|
||||
int postBufferCount;
|
||||
int unregisterBuffersCount;
|
||||
};
|
||||
|
||||
status_t MSurface::registerBuffers(const BufferHeap& buffers) {
|
||||
INFO("%s", __func__);
|
||||
Mutex::Autolock _l(mLock);
|
||||
++registerBuffersCount;
|
||||
mCond.signal();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void MSurface::postBuffer(ssize_t offset) {
|
||||
// INFO("%s", __func__);
|
||||
Mutex::Autolock _l(mLock);
|
||||
++postBufferCount;
|
||||
mCond.signal();
|
||||
}
|
||||
|
||||
void MSurface::unregisterBuffers() {
|
||||
INFO("%s", __func__);
|
||||
Mutex::Autolock _l(mLock);
|
||||
++unregisterBuffersCount;
|
||||
mCond.signal();
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
|
||||
INFO("%s", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t MSurface::setBufferCount(int bufferCount) {
|
||||
INFO("%s", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MSurface::clearStat() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
registerBuffersCount = 0;
|
||||
postBufferCount = 0;
|
||||
unregisterBuffersCount = 0;
|
||||
}
|
||||
|
||||
void MSurface::waitUntil(int c0, int c1, int c2) {
|
||||
INFO("waitUntil: %d %d %d", c0, c1, c2);
|
||||
Mutex::Autolock _l(mLock);
|
||||
while (true) {
|
||||
if (registerBuffersCount >= c0 &&
|
||||
postBufferCount >= c1 &&
|
||||
unregisterBuffersCount >= c2) {
|
||||
break;
|
||||
}
|
||||
mCond.wait(mLock);
|
||||
}
|
||||
}
|
||||
|
||||
sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
|
||||
int32_t orientation) {
|
||||
// Not implemented.
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities to use the Holder service
|
||||
//
|
||||
sp<IHolder> getHolder() {
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
ASSERT(sm != 0);
|
||||
sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
|
||||
ASSERT(binder != 0);
|
||||
sp<IHolder> holder = interface_cast<IHolder>(binder);
|
||||
ASSERT(holder != 0);
|
||||
return holder;
|
||||
}
|
||||
|
||||
void putTempObject(sp<IBinder> obj) {
|
||||
INFO("%s", __func__);
|
||||
getHolder()->put(obj);
|
||||
}
|
||||
|
||||
sp<IBinder> getTempObject() {
|
||||
INFO("%s", __func__);
|
||||
return getHolder()->get();
|
||||
}
|
||||
|
||||
void clearTempObject() {
|
||||
INFO("%s", __func__);
|
||||
getHolder()->clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Get a Camera Service
|
||||
//
|
||||
sp<ICameraService> getCameraService() {
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
ASSERT(sm != 0);
|
||||
sp<IBinder> binder = sm->getService(String16("media.camera"));
|
||||
ASSERT(binder != 0);
|
||||
sp<ICameraService> cs = interface_cast<ICameraService>(binder);
|
||||
ASSERT(cs != 0);
|
||||
return cs;
|
||||
}
|
||||
|
||||
int getNumberOfCameras() {
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
return cs->getNumberOfCameras();
|
||||
}
|
||||
|
||||
//
|
||||
// Various Connect Tests
|
||||
//
|
||||
void testConnect(int cameraId) {
|
||||
INFO("%s", __func__);
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
sp<ICamera> c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
c->disconnect();
|
||||
}
|
||||
|
||||
void testAllowConnectOnceOnly(int cameraId) {
|
||||
INFO("%s", __func__);
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
// Connect the first client.
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
sp<ICamera> c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
// Same client -- ok.
|
||||
ASSERT(cs->connect(cc, cameraId) != 0);
|
||||
// Different client -- not ok.
|
||||
sp<MCameraClient> cc2 = new MCameraClient();
|
||||
ASSERT(cs->connect(cc2, cameraId) == 0);
|
||||
c->disconnect();
|
||||
}
|
||||
|
||||
void testReconnectFailed() {
|
||||
INFO("%s", __func__);
|
||||
sp<ICamera> c = interface_cast<ICamera>(getTempObject());
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
ASSERT(c->connect(cc) != NO_ERROR);
|
||||
}
|
||||
|
||||
void testReconnectSuccess() {
|
||||
INFO("%s", __func__);
|
||||
sp<ICamera> c = interface_cast<ICamera>(getTempObject());
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
ASSERT(c->connect(cc) == NO_ERROR);
|
||||
c->disconnect();
|
||||
}
|
||||
|
||||
void testLockFailed() {
|
||||
INFO("%s", __func__);
|
||||
sp<ICamera> c = interface_cast<ICamera>(getTempObject());
|
||||
ASSERT(c->lock() != NO_ERROR);
|
||||
}
|
||||
|
||||
void testLockUnlockSuccess() {
|
||||
INFO("%s", __func__);
|
||||
sp<ICamera> c = interface_cast<ICamera>(getTempObject());
|
||||
ASSERT(c->lock() == NO_ERROR);
|
||||
ASSERT(c->unlock() == NO_ERROR);
|
||||
}
|
||||
|
||||
void testLockSuccess() {
|
||||
INFO("%s", __func__);
|
||||
sp<ICamera> c = interface_cast<ICamera>(getTempObject());
|
||||
ASSERT(c->lock() == NO_ERROR);
|
||||
c->disconnect();
|
||||
}
|
||||
|
||||
//
|
||||
// Run the connect tests in another process.
|
||||
//
|
||||
const char *gExecutable;
|
||||
|
||||
struct FunctionTableEntry {
|
||||
const char *name;
|
||||
void (*func)();
|
||||
};
|
||||
|
||||
FunctionTableEntry function_table[] = {
|
||||
#define ENTRY(x) {#x, &x}
|
||||
ENTRY(testReconnectFailed),
|
||||
ENTRY(testReconnectSuccess),
|
||||
ENTRY(testLockUnlockSuccess),
|
||||
ENTRY(testLockFailed),
|
||||
ENTRY(testLockSuccess),
|
||||
#undef ENTRY
|
||||
};
|
||||
|
||||
void runFunction(const char *tag) {
|
||||
INFO("runFunction: %s", tag);
|
||||
int entries = sizeof(function_table) / sizeof(function_table[0]);
|
||||
for (int i = 0; i < entries; i++) {
|
||||
if (strcmp(function_table[i].name, tag) == 0) {
|
||||
(*function_table[i].func)();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
void runInAnotherProcess(const char *tag) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
execlp(gExecutable, gExecutable, tag, NULL);
|
||||
ASSERT(0);
|
||||
} else {
|
||||
int status;
|
||||
ASSERT_EQ(pid, wait(&status));
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
}
|
||||
|
||||
void testReconnect(int cameraId) {
|
||||
INFO("%s", __func__);
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
sp<ICamera> c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
// Reconnect to the same client -- ok.
|
||||
ASSERT(c->connect(cc) == NO_ERROR);
|
||||
// Reconnect to a different client (but the same pid) -- ok.
|
||||
sp<MCameraClient> cc2 = new MCameraClient();
|
||||
ASSERT(c->connect(cc2) == NO_ERROR);
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
|
||||
void testLockUnlock(int cameraId) {
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
sp<ICamera> c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
// We can lock as many times as we want.
|
||||
ASSERT(c->lock() == NO_ERROR);
|
||||
ASSERT(c->lock() == NO_ERROR);
|
||||
// Lock from a different process -- not ok.
|
||||
putTempObject(c->asBinder());
|
||||
runInAnotherProcess("testLockFailed");
|
||||
// Unlock then lock from a different process -- ok.
|
||||
ASSERT(c->unlock() == NO_ERROR);
|
||||
runInAnotherProcess("testLockUnlockSuccess");
|
||||
// Unlock then lock from a different process -- ok.
|
||||
runInAnotherProcess("testLockSuccess");
|
||||
clearTempObject();
|
||||
}
|
||||
|
||||
void testReconnectFromAnotherProcess(int cameraId) {
|
||||
INFO("%s", __func__);
|
||||
|
||||
sp<ICameraService> cs = getCameraService();
|
||||
sp<MCameraClient> cc = new MCameraClient();
|
||||
sp<ICamera> c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
// Reconnect from a different process -- not ok.
|
||||
putTempObject(c->asBinder());
|
||||
runInAnotherProcess("testReconnectFailed");
|
||||
// Unlock then reconnect from a different process -- ok.
|
||||
ASSERT(c->unlock() == NO_ERROR);
|
||||
runInAnotherProcess("testReconnectSuccess");
|
||||
clearTempObject();
|
||||
}
|
||||
|
||||
// We need to flush the command buffer after the reference
|
||||
// to ICamera is gone. The sleep is for the server to run
|
||||
// the destructor for it.
|
||||
static void flushCommands() {
|
||||
IPCThreadState::self()->flushCommands();
|
||||
usleep(200000); // 200ms
|
||||
}
|
||||
|
||||
// Run a test case
|
||||
#define RUN(class_name, cameraId) do { \
|
||||
{ \
|
||||
INFO(#class_name); \
|
||||
class_name instance; \
|
||||
instance.init(cameraId); \
|
||||
instance.run(); \
|
||||
} \
|
||||
flushCommands(); \
|
||||
} while(0)
|
||||
|
||||
// Base test case after the the camera is connected.
|
||||
class AfterConnect {
|
||||
public:
|
||||
void init(int cameraId) {
|
||||
cs = getCameraService();
|
||||
cc = new MCameraClient();
|
||||
c = cs->connect(cc, cameraId);
|
||||
ASSERT(c != 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
sp<ICameraService> cs;
|
||||
sp<MCameraClient> cc;
|
||||
sp<ICamera> c;
|
||||
|
||||
~AfterConnect() {
|
||||
c->disconnect();
|
||||
c.clear();
|
||||
cc.clear();
|
||||
cs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class TestSetPreviewDisplay : public AfterConnect {
|
||||
public:
|
||||
void run() {
|
||||
sp<MSurface> surface = new MSurface();
|
||||
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestStartPreview : public AfterConnect {
|
||||
public:
|
||||
void run() {
|
||||
sp<MSurface> surface = new MSurface();
|
||||
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
|
||||
|
||||
ASSERT(c->startPreview() == NO_ERROR);
|
||||
ASSERT(c->previewEnabled() == true);
|
||||
|
||||
surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
|
||||
surface->clearStat();
|
||||
|
||||
sp<MSurface> another_surface = new MSurface();
|
||||
c->setPreviewDisplay(another_surface); // just to make sure unregisterBuffers
|
||||
// is called.
|
||||
surface->waitUntil(0, 0, 1); // needs unregisterBuffers
|
||||
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestStartPreviewWithoutDisplay : public AfterConnect {
|
||||
public:
|
||||
void run() {
|
||||
ASSERT(c->startPreview() == NO_ERROR);
|
||||
ASSERT(c->previewEnabled() == true);
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// Base test case after the the camera is connected and the preview is started.
|
||||
class AfterStartPreview : public AfterConnect {
|
||||
public:
|
||||
void init(int cameraId) {
|
||||
AfterConnect::init(cameraId);
|
||||
surface = new MSurface();
|
||||
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
|
||||
ASSERT(c->startPreview() == NO_ERROR);
|
||||
}
|
||||
|
||||
protected:
|
||||
sp<MSurface> surface;
|
||||
|
||||
~AfterStartPreview() {
|
||||
surface.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class TestAutoFocus : public AfterStartPreview {
|
||||
public:
|
||||
void run() {
|
||||
cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
|
||||
c->autoFocus();
|
||||
cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestStopPreview : public AfterStartPreview {
|
||||
public:
|
||||
void run() {
|
||||
ASSERT(c->previewEnabled() == true);
|
||||
c->stopPreview();
|
||||
ASSERT(c->previewEnabled() == false);
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestTakePicture: public AfterStartPreview {
|
||||
public:
|
||||
void run() {
|
||||
ASSERT(c->takePicture() == NO_ERROR);
|
||||
cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
|
||||
cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
|
||||
cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
|
||||
c->stopPreview();
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestTakeMultiplePictures: public AfterStartPreview {
|
||||
public:
|
||||
void run() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
cc->clearStat();
|
||||
ASSERT(c->takePicture() == NO_ERROR);
|
||||
cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
|
||||
cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
|
||||
cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
|
||||
}
|
||||
c->disconnect();
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TestGetParameters: public AfterStartPreview {
|
||||
public:
|
||||
void run() {
|
||||
String8 param_str = c->getParameters();
|
||||
INFO("%s", static_cast<const char*>(param_str));
|
||||
}
|
||||
};
|
||||
|
||||
static bool getNextSize(const char **ptrS, int *w, int *h) {
|
||||
const char *s = *ptrS;
|
||||
|
||||
// skip over ','
|
||||
if (*s == ',') s++;
|
||||
|
||||
// remember start position in p
|
||||
const char *p = s;
|
||||
while (*s != '\0' && *s != 'x') {
|
||||
s++;
|
||||
}
|
||||
if (*s == '\0') return false;
|
||||
|
||||
// get the width
|
||||
*w = atoi(p);
|
||||
|
||||
// skip over 'x'
|
||||
ASSERT(*s == 'x');
|
||||
p = s + 1;
|
||||
while (*s != '\0' && *s != ',') {
|
||||
s++;
|
||||
}
|
||||
|
||||
// get the height
|
||||
*h = atoi(p);
|
||||
*ptrS = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
class TestPictureSize : public AfterStartPreview {
|
||||
public:
|
||||
void checkOnePicture(int w, int h) {
|
||||
const float rate = 0.9; // byte per pixel limit
|
||||
int pixels = w * h;
|
||||
|
||||
CameraParameters param(c->getParameters());
|
||||
param.setPictureSize(w, h);
|
||||
// disable thumbnail to get more accurate size.
|
||||
param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
|
||||
param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
|
||||
c->setParameters(param.flatten());
|
||||
|
||||
cc->clearStat();
|
||||
ASSERT(c->takePicture() == NO_ERROR);
|
||||
cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
|
||||
//cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
|
||||
cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
|
||||
cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
|
||||
int(pixels * rate));
|
||||
cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
|
||||
cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
|
||||
}
|
||||
|
||||
void run() {
|
||||
CameraParameters param(c->getParameters());
|
||||
int w, h;
|
||||
const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
|
||||
while (getNextSize(&s, &w, &h)) {
|
||||
LOGD("checking picture size %dx%d", w, h);
|
||||
checkOnePicture(w, h);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TestPreviewCallbackFlag : public AfterConnect {
|
||||
public:
|
||||
void run() {
|
||||
sp<MSurface> surface = new MSurface();
|
||||
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
|
||||
|
||||
// Try all flag combinations.
|
||||
for (int v = 0; v < 8; v++) {
|
||||
LOGD("TestPreviewCallbackFlag: flag=%d", v);
|
||||
usleep(100000); // sleep a while to clear the in-flight callbacks.
|
||||
cc->clearStat();
|
||||
c->setPreviewCallbackFlag(v);
|
||||
ASSERT(c->previewEnabled() == false);
|
||||
ASSERT(c->startPreview() == NO_ERROR);
|
||||
ASSERT(c->previewEnabled() == true);
|
||||
sleep(2);
|
||||
c->stopPreview();
|
||||
if ((v & 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) {
|
||||
cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
|
||||
} else {
|
||||
cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TestRecording : public AfterConnect {
|
||||
public:
|
||||
void run() {
|
||||
ASSERT(c->recordingEnabled() == false);
|
||||
sp<MSurface> surface = new MSurface();
|
||||
ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
|
||||
c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
|
||||
cc->setReleaser(c.get());
|
||||
c->startRecording();
|
||||
ASSERT(c->recordingEnabled() == true);
|
||||
sleep(2);
|
||||
c->stopRecording();
|
||||
usleep(100000); // sleep a while to clear the in-flight callbacks.
|
||||
cc->setReleaser(NULL);
|
||||
cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
|
||||
}
|
||||
};
|
||||
|
||||
class TestPreviewSize : public AfterStartPreview {
|
||||
public:
|
||||
void checkOnePicture(int w, int h) {
|
||||
int size = w*h*3/2; // should read from parameters
|
||||
|
||||
c->stopPreview();
|
||||
|
||||
CameraParameters param(c->getParameters());
|
||||
param.setPreviewSize(w, h);
|
||||
c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
|
||||
c->setParameters(param.flatten());
|
||||
|
||||
c->startPreview();
|
||||
|
||||
cc->clearStat();
|
||||
cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
|
||||
cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
|
||||
}
|
||||
|
||||
void run() {
|
||||
CameraParameters param(c->getParameters());
|
||||
int w, h;
|
||||
const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
|
||||
while (getNextSize(&s, &w, &h)) {
|
||||
LOGD("checking preview size %dx%d", w, h);
|
||||
checkOnePicture(w, h);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void runHolderService() {
|
||||
defaultServiceManager()->addService(
|
||||
String16("CameraServiceTest.Holder"), new HolderService());
|
||||
ProcessState::self()->startThreadPool();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 1) {
|
||||
runFunction(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
INFO("CameraServiceTest start");
|
||||
gExecutable = argv[0];
|
||||
runHolderService();
|
||||
int n = getNumberOfCameras();
|
||||
INFO("%d Cameras available", n);
|
||||
|
||||
for (int id = 0; id < n; id++) {
|
||||
INFO("Testing camera %d", id);
|
||||
testConnect(id); flushCommands();
|
||||
testAllowConnectOnceOnly(id); flushCommands();
|
||||
testReconnect(id); flushCommands();
|
||||
testLockUnlock(id); flushCommands();
|
||||
testReconnectFromAnotherProcess(id); flushCommands();
|
||||
|
||||
RUN(TestSetPreviewDisplay, id);
|
||||
RUN(TestStartPreview, id);
|
||||
RUN(TestStartPreviewWithoutDisplay, id);
|
||||
RUN(TestAutoFocus, id);
|
||||
RUN(TestStopPreview, id);
|
||||
RUN(TestTakePicture, id);
|
||||
RUN(TestTakeMultiplePictures, id);
|
||||
RUN(TestGetParameters, id);
|
||||
RUN(TestPictureSize, id);
|
||||
RUN(TestPreviewCallbackFlag, id);
|
||||
RUN(TestRecording, id);
|
||||
RUN(TestPreviewSize, id);
|
||||
}
|
||||
|
||||
INFO("CameraServiceTest finished");
|
||||
}
|
@ -10,7 +10,7 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libutils
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/../../libs/surfaceflinger
|
||||
$(LOCAL_PATH)/../../services/surfaceflinger
|
||||
|
||||
LOCAL_MODULE:= surfaceflinger
|
||||
|
||||
|
@ -1,466 +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"
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
//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;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
|
||||
{
|
||||
LOGV("A2dpAudioStreamOut destructor");
|
||||
standby();
|
||||
close();
|
||||
LOGV("A2dpAudioStreamOut destructor returning from close()");
|
||||
}
|
||||
|
||||
ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
|
||||
size_t remaining = bytes;
|
||||
status_t status = -1;
|
||||
|
||||
if (!mBluetoothEnabled || mClosing || mSuspended) {
|
||||
LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
|
||||
mBluetoothEnabled %d, mClosing %d, mSuspended %d",
|
||||
mBluetoothEnabled, mClosing, mSuspended);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
status = init();
|
||||
if (status < 0)
|
||||
goto Error;
|
||||
|
||||
while (remaining > 0) {
|
||||
status = a2dp_write(mData, buffer, remaining);
|
||||
if (status <= 0) {
|
||||
LOGE("a2dp_write failed err: %d\n", status);
|
||||
goto Error;
|
||||
}
|
||||
remaining -= status;
|
||||
buffer = ((char *)buffer) + status;
|
||||
}
|
||||
|
||||
mStandby = false;
|
||||
|
||||
return bytes;
|
||||
|
||||
Error:
|
||||
// Simulate audio output timing in case of error
|
||||
usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
|
||||
|
||||
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()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (mClosing) {
|
||||
LOGV("Ignore standby, closing");
|
||||
return result;
|
||||
}
|
||||
|
||||
Mutex::Autolock lock(mLock);
|
||||
|
||||
if (!mStandby) {
|
||||
result = a2dp_stop(mData);
|
||||
if (result == 0)
|
||||
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");
|
||||
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()
|
||||
{
|
||||
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
|
@ -1,135 +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);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
friend class A2dpAudioStreamOut;
|
||||
|
||||
A2dpAudioStreamOut* mOutput;
|
||||
AudioHardwareInterface *mHardwareInterface;
|
||||
char mA2dpAddress[20];
|
||||
bool mBluetoothEnabled;
|
||||
bool mSuspended;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // A2DP_AUDIO_HARDWARE_H
|
@ -1,131 +0,0 @@
|
||||
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:= \
|
||||
AudioFlinger.cpp \
|
||||
AudioMixer.cpp.arm \
|
||||
AudioResampler.cpp.arm \
|
||||
AudioResamplerSinc.cpp.arm \
|
||||
AudioResamplerCubic.cpp.arm \
|
||||
AudioPolicyService.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libutils \
|
||||
libbinder \
|
||||
libmedia \
|
||||
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
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_LDLIBS += -ldl
|
||||
else
|
||||
LOCAL_SHARED_LIBRARIES += libdl
|
||||
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
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD_USE_LVMX),true)
|
||||
LOCAL_CFLAGS += -DLVMX
|
||||
LOCAL_C_INCLUDES += vendor/nxp
|
||||
LOCAL_STATIC_LIBRARIES += liblifevibes
|
||||
LOCAL_SHARED_LIBRARIES += liblvmxservice
|
||||
# LOCAL_SHARED_LIBRARIES += liblvmxipc
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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_BUFFER_PROVIDER_H
|
||||
#define ANDROID_AUDIO_BUFFER_PROVIDER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/Errors.h>
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioBufferProvider
|
||||
{
|
||||
public:
|
||||
|
||||
struct Buffer {
|
||||
union {
|
||||
void* raw;
|
||||
short* i16;
|
||||
int8_t* i8;
|
||||
};
|
||||
size_t frameCount;
|
||||
};
|
||||
|
||||
virtual ~AudioBufferProvider() {}
|
||||
|
||||
virtual status_t getNextBuffer(Buffer* buffer) = 0;
|
||||
virtual void releaseBuffer(Buffer* buffer) = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H
|
@ -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
|
@ -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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -1,182 +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"
|
||||
};
|
||||
|
||||
static const char* routeNone = "NONE";
|
||||
|
||||
static const char* displayMode(int mode)
|
||||
{
|
||||
if ((mode < -2) || (mode > 2))
|
||||
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
|
@ -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
|
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -1,207 +0,0 @@
|
||||
/* //device/include/server/AudioFlinger/AudioMixer.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_MIXER_H
|
||||
#define ANDROID_AUDIO_MIXER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "AudioBufferProvider.h"
|
||||
#include "AudioResampler.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioMixer
|
||||
{
|
||||
public:
|
||||
AudioMixer(size_t frameCount, uint32_t sampleRate);
|
||||
|
||||
~AudioMixer();
|
||||
|
||||
static const uint32_t MAX_NUM_TRACKS = 32;
|
||||
static const uint32_t MAX_NUM_CHANNELS = 2;
|
||||
|
||||
static const uint16_t UNITY_GAIN = 0x1000;
|
||||
|
||||
enum { // names
|
||||
|
||||
// track units (32 units)
|
||||
TRACK0 = 0x1000,
|
||||
|
||||
// enable/disable
|
||||
MIXING = 0x2000,
|
||||
|
||||
// setParameter targets
|
||||
TRACK = 0x3000,
|
||||
RESAMPLE = 0x3001,
|
||||
RAMP_VOLUME = 0x3002, // ramp to new volume
|
||||
VOLUME = 0x3003, // don't ramp
|
||||
|
||||
// set Parameter names
|
||||
// for target TRACK
|
||||
CHANNEL_COUNT = 0x4000,
|
||||
FORMAT = 0x4001,
|
||||
MAIN_BUFFER = 0x4002,
|
||||
AUX_BUFFER = 0x4003,
|
||||
// for TARGET RESAMPLE
|
||||
SAMPLE_RATE = 0x4100,
|
||||
// for TARGET VOLUME (8 channels max)
|
||||
VOLUME0 = 0x4200,
|
||||
VOLUME1 = 0x4201,
|
||||
AUXLEVEL = 0x4210,
|
||||
};
|
||||
|
||||
|
||||
int getTrackName();
|
||||
void deleteTrackName(int name);
|
||||
|
||||
status_t enable(int name);
|
||||
status_t disable(int name);
|
||||
|
||||
status_t setActiveTrack(int track);
|
||||
status_t setParameter(int target, int name, void *value);
|
||||
|
||||
status_t setBufferProvider(AudioBufferProvider* bufferProvider);
|
||||
void process();
|
||||
|
||||
uint32_t trackNames() const { return mTrackNames; }
|
||||
|
||||
static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
|
||||
|
||||
private:
|
||||
|
||||
enum {
|
||||
NEEDS_CHANNEL_COUNT__MASK = 0x00000003,
|
||||
NEEDS_FORMAT__MASK = 0x000000F0,
|
||||
NEEDS_MUTE__MASK = 0x00000100,
|
||||
NEEDS_RESAMPLE__MASK = 0x00001000,
|
||||
NEEDS_AUX__MASK = 0x00010000,
|
||||
};
|
||||
|
||||
enum {
|
||||
NEEDS_CHANNEL_1 = 0x00000000,
|
||||
NEEDS_CHANNEL_2 = 0x00000001,
|
||||
|
||||
NEEDS_FORMAT_16 = 0x00000010,
|
||||
|
||||
NEEDS_MUTE_DISABLED = 0x00000000,
|
||||
NEEDS_MUTE_ENABLED = 0x00000100,
|
||||
|
||||
NEEDS_RESAMPLE_DISABLED = 0x00000000,
|
||||
NEEDS_RESAMPLE_ENABLED = 0x00001000,
|
||||
|
||||
NEEDS_AUX_DISABLED = 0x00000000,
|
||||
NEEDS_AUX_ENABLED = 0x00010000,
|
||||
};
|
||||
|
||||
static inline int32_t applyVolume(int32_t in, int32_t v) {
|
||||
return in * v;
|
||||
}
|
||||
|
||||
|
||||
struct state_t;
|
||||
struct track_t;
|
||||
|
||||
typedef void (*mix_t)(state_t* state);
|
||||
typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
|
||||
static const int BLOCKSIZE = 16; // 4 cache lines
|
||||
|
||||
struct track_t {
|
||||
uint32_t needs;
|
||||
|
||||
union {
|
||||
int16_t volume[2]; // [0]3.12 fixed point
|
||||
int32_t volumeRL;
|
||||
};
|
||||
|
||||
int32_t prevVolume[2];
|
||||
|
||||
int32_t volumeInc[2];
|
||||
int32_t auxLevel;
|
||||
int32_t auxInc;
|
||||
int32_t prevAuxLevel;
|
||||
|
||||
uint16_t frameCount;
|
||||
|
||||
uint8_t channelCount : 4;
|
||||
uint8_t enabled : 1;
|
||||
uint8_t reserved0 : 3;
|
||||
uint8_t format;
|
||||
|
||||
AudioBufferProvider* bufferProvider;
|
||||
mutable AudioBufferProvider::Buffer buffer;
|
||||
|
||||
hook_t hook;
|
||||
void const* in; // current location in buffer
|
||||
|
||||
AudioResampler* resampler;
|
||||
uint32_t sampleRate;
|
||||
int32_t* mainBuffer;
|
||||
int32_t* auxBuffer;
|
||||
|
||||
bool setResampler(uint32_t sampleRate, uint32_t devSampleRate);
|
||||
bool doesResample() const;
|
||||
void adjustVolumeRamp(bool aux);
|
||||
};
|
||||
|
||||
// pad to 32-bytes to fill cache line
|
||||
struct state_t {
|
||||
uint32_t enabledTracks;
|
||||
uint32_t needsChanged;
|
||||
size_t frameCount;
|
||||
mix_t hook;
|
||||
int32_t *outputTemp;
|
||||
int32_t *resampleTemp;
|
||||
int32_t reserved[2];
|
||||
track_t tracks[32]; __attribute__((aligned(32)));
|
||||
};
|
||||
|
||||
int mActiveTrack;
|
||||
uint32_t mTrackNames;
|
||||
const uint32_t mSampleRate;
|
||||
|
||||
state_t mState __attribute__((aligned(32)));
|
||||
|
||||
void invalidateState(uint32_t mask);
|
||||
|
||||
static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
||||
static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
||||
static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
||||
static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
||||
static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
|
||||
static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
|
||||
|
||||
static void process__validate(state_t* state);
|
||||
static void process__nop(state_t* state);
|
||||
static void process__genericNoResampling(state_t* state);
|
||||
static void process__genericResampling(state_t* state);
|
||||
static void process__OneTrack16BitsStereoNoResampling(state_t* state);
|
||||
static void process__TwoTracks16BitsStereoNoResampling(state_t* state);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_AUDIO_MIXER_H
|
File diff suppressed because it is too large
Load Diff
@ -1,924 +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 "AudioPolicyService"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#undef __STRICT_ANSI__
|
||||
#define __STDINT_LIMITS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <utils/Log.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#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>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// the sim build doesn't have gettid
|
||||
|
||||
#ifndef HAVE_GETTID
|
||||
# define gettid getpid
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
|
||||
static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
|
||||
static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
|
||||
|
||||
static const int kDumpLockRetries = 50;
|
||||
static const int kDumpLockSleep = 20000;
|
||||
|
||||
static bool checkPermission() {
|
||||
#ifndef HAVE_ANDROID_OS
|
||||
return true;
|
||||
#endif
|
||||
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
|
||||
bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
|
||||
if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AudioPolicyService::AudioPolicyService()
|
||||
: BnAudioPolicyService() , mpPolicyManager(NULL)
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
|
||||
// start tone playback thread
|
||||
mTonePlaybackThread = new AudioCommandThread(String8(""));
|
||||
// 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
|
||||
|
||||
// load properties
|
||||
property_get("ro.camera.sound.forced", value, "0");
|
||||
mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
|
||||
}
|
||||
|
||||
AudioPolicyService::~AudioPolicyService()
|
||||
{
|
||||
mTonePlaybackThread->exit();
|
||||
mTonePlaybackThread.clear();
|
||||
mAudioCommandThread->exit();
|
||||
mAudioCommandThread.clear();
|
||||
|
||||
if (mpPolicyManager) {
|
||||
delete mpPolicyManager;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
|
||||
AudioSystem::device_connection_state state,
|
||||
const char *device_address)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
LOGV("setDeviceConnectionState() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
|
||||
}
|
||||
|
||||
AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
|
||||
const char *device_address)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return AudioSystem::DEVICE_STATE_UNAVAILABLE;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return AudioSystem::DEVICE_STATE_UNAVAILABLE;
|
||||
}
|
||||
return mpPolicyManager->getDeviceConnectionState(device, device_address);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::setPhoneState(int state)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (state < 0 || state >= AudioSystem::NUM_MODES) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
LOGV("setPhoneState() tid %d", gettid());
|
||||
|
||||
// TODO: check if it is more appropriate to do it in platform specific policy manager
|
||||
AudioSystem::setMode(state);
|
||||
|
||||
Mutex::Autolock _l(mLock);
|
||||
mpPolicyManager->setPhoneState(state);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
mpPolicyManager->setRingerMode(mode, mask);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
LOGV("setForceUse() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
mpPolicyManager->setForceUse(usage, config);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return AudioSystem::FORCE_NONE;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return AudioSystem::FORCE_NONE;
|
||||
}
|
||||
if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
|
||||
return AudioSystem::FORCE_NONE;
|
||||
}
|
||||
return mpPolicyManager->getForceUse(usage);
|
||||
}
|
||||
|
||||
audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
|
||||
uint32_t samplingRate,
|
||||
uint32_t format,
|
||||
uint32_t channels,
|
||||
AudioSystem::output_flags flags)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return 0;
|
||||
}
|
||||
LOGV("getOutput() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
LOGV("startOutput() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->startOutput(output, stream);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
LOGV("stopOutput() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->stopOutput(output, stream);
|
||||
}
|
||||
|
||||
void AudioPolicyService::releaseOutput(audio_io_handle_t output)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return;
|
||||
}
|
||||
LOGV("releaseOutput() tid %d", gettid());
|
||||
Mutex::Autolock _l(mLock);
|
||||
mpPolicyManager->releaseOutput(output);
|
||||
}
|
||||
|
||||
audio_io_handle_t AudioPolicyService::getInput(int inputSource,
|
||||
uint32_t samplingRate,
|
||||
uint32_t format,
|
||||
uint32_t channels,
|
||||
AudioSystem::audio_in_acoustics acoustics)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return 0;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::startInput(audio_io_handle_t input)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->startInput(input);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::stopInput(audio_io_handle_t input)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
return mpPolicyManager->stopInput(input);
|
||||
}
|
||||
|
||||
void AudioPolicyService::releaseInput(audio_io_handle_t input)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
mpPolicyManager->releaseInput(input);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
|
||||
int indexMin,
|
||||
int indexMax)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
return mpPolicyManager->setStreamVolumeIndex(stream, index);
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
|
||||
{
|
||||
if (mpPolicyManager == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
if (!checkPermission()) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
return mpPolicyManager->getStreamVolumeIndex(stream, index);
|
||||
}
|
||||
|
||||
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
|
||||
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
|
||||
}
|
||||
|
||||
static bool tryLock(Mutex& mutex)
|
||||
{
|
||||
bool locked = false;
|
||||
for (int i = 0; i < kDumpLockRetries; ++i) {
|
||||
if (mutex.tryLock() == NO_ERROR) {
|
||||
locked = true;
|
||||
break;
|
||||
}
|
||||
usleep(kDumpLockSleep);
|
||||
}
|
||||
return locked;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::dumpInternals(int fd)
|
||||
{
|
||||
const size_t SIZE = 256;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
|
||||
snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
|
||||
result.append(buffer);
|
||||
snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
|
||||
result.append(buffer);
|
||||
snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
|
||||
result.append(buffer);
|
||||
|
||||
write(fd, result.string(), result.size());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
|
||||
{
|
||||
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
|
||||
dumpPermissionDenial(fd);
|
||||
} else {
|
||||
bool locked = tryLock(mLock);
|
||||
if (!locked) {
|
||||
String8 result(kDeadlockedString);
|
||||
write(fd, result.string(), result.size());
|
||||
}
|
||||
|
||||
dumpInternals(fd);
|
||||
if (mAudioCommandThread != NULL) {
|
||||
mAudioCommandThread->dump(fd);
|
||||
}
|
||||
if (mTonePlaybackThread != NULL) {
|
||||
mTonePlaybackThread->dump(fd);
|
||||
}
|
||||
|
||||
if (mpPolicyManager) {
|
||||
mpPolicyManager->dump(fd);
|
||||
}
|
||||
|
||||
if (locked) mLock.unlock();
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::dumpPermissionDenial(int fd)
|
||||
{
|
||||
const size_t SIZE = 256;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
snprintf(buffer, SIZE, "Permission Denial: "
|
||||
"can't dump AudioPolicyService from pid=%d, uid=%d\n",
|
||||
IPCThreadState::self()->getCallingPid(),
|
||||
IPCThreadState::self()->getCallingUid());
|
||||
result.append(buffer);
|
||||
write(fd, result.string(), result.size());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||
{
|
||||
return BnAudioPolicyService::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AudioPolicyService::instantiate() {
|
||||
defaultServiceManager()->addService(
|
||||
String16("media.audio_policy"), new AudioPolicyService());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
: Thread(false), mName(name)
|
||||
{
|
||||
mpToneGenerator = NULL;
|
||||
}
|
||||
|
||||
|
||||
AudioPolicyService::AudioCommandThread::~AudioCommandThread()
|
||||
{
|
||||
if (mName != "" && !mAudioCommands.isEmpty()) {
|
||||
release_wake_lock(mName.string());
|
||||
}
|
||||
mAudioCommands.clear();
|
||||
if (mpToneGenerator != NULL) delete mpToneGenerator;
|
||||
}
|
||||
|
||||
void AudioPolicyService::AudioCommandThread::onFirstRef()
|
||||
{
|
||||
if (mName != "") {
|
||||
run(mName.string(), ANDROID_PRIORITY_AUDIO);
|
||||
} else {
|
||||
run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioPolicyService::AudioCommandThread::threadLoop()
|
||||
{
|
||||
nsecs_t waitTime = INT64_MAX;
|
||||
|
||||
mLock.lock();
|
||||
while (!exitPending())
|
||||
{
|
||||
while(!mAudioCommands.isEmpty()) {
|
||||
nsecs_t curTime = systemTime();
|
||||
// commands are sorted by increasing time stamp: execute them from index 0 and up
|
||||
if (mAudioCommands[0]->mTime <= curTime) {
|
||||
AudioCommand *command = mAudioCommands[0];
|
||||
mAudioCommands.removeAt(0);
|
||||
mLastCommand = *command;
|
||||
|
||||
switch (command->mCommand) {
|
||||
case START_TONE: {
|
||||
mLock.unlock();
|
||||
ToneData *data = (ToneData *)command->mParam;
|
||||
LOGV("AudioCommandThread() processing start tone %d on stream %d",
|
||||
data->mType, data->mStream);
|
||||
if (mpToneGenerator != NULL)
|
||||
delete mpToneGenerator;
|
||||
mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
|
||||
mpToneGenerator->startTone(data->mType);
|
||||
delete data;
|
||||
mLock.lock();
|
||||
}break;
|
||||
case STOP_TONE: {
|
||||
mLock.unlock();
|
||||
LOGV("AudioCommandThread() processing stop tone");
|
||||
if (mpToneGenerator != NULL) {
|
||||
mpToneGenerator->stopTone();
|
||||
delete mpToneGenerator;
|
||||
mpToneGenerator = NULL;
|
||||
}
|
||||
mLock.lock();
|
||||
}break;
|
||||
case SET_VOLUME: {
|
||||
VolumeData *data = (VolumeData *)command->mParam;
|
||||
LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
|
||||
command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.signal();
|
||||
mWaitWorkCV.wait(mLock);
|
||||
}
|
||||
delete data;
|
||||
}break;
|
||||
case SET_PARAMETERS: {
|
||||
ParametersData *data = (ParametersData *)command->mParam;
|
||||
LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
|
||||
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.signal();
|
||||
mWaitWorkCV.wait(mLock);
|
||||
}
|
||||
delete data;
|
||||
}break;
|
||||
case SET_VOICE_VOLUME: {
|
||||
VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
|
||||
LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
|
||||
command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.signal();
|
||||
mWaitWorkCV.wait(mLock);
|
||||
}
|
||||
delete data;
|
||||
}break;
|
||||
default:
|
||||
LOGW("AudioCommandThread() unknown command %d", command->mCommand);
|
||||
}
|
||||
delete command;
|
||||
waitTime = INT64_MAX;
|
||||
} else {
|
||||
waitTime = mAudioCommands[0]->mTime - curTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// release delayed commands wake lock
|
||||
if (mName != "" && mAudioCommands.isEmpty()) {
|
||||
release_wake_lock(mName.string());
|
||||
}
|
||||
LOGV("AudioCommandThread() going to sleep");
|
||||
mWaitWorkCV.waitRelative(mLock, waitTime);
|
||||
LOGV("AudioCommandThread() waking up");
|
||||
}
|
||||
mLock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::AudioCommandThread::dump(int fd)
|
||||
{
|
||||
const size_t SIZE = 256;
|
||||
char buffer[SIZE];
|
||||
String8 result;
|
||||
|
||||
snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
|
||||
result.append(buffer);
|
||||
write(fd, result.string(), result.size());
|
||||
|
||||
bool locked = tryLock(mLock);
|
||||
if (!locked) {
|
||||
String8 result2(kCmdDeadlockedString);
|
||||
write(fd, result2.string(), result2.size());
|
||||
}
|
||||
|
||||
snprintf(buffer, SIZE, "- Commands:\n");
|
||||
result = String8(buffer);
|
||||
result.append(" Command Time Wait pParam\n");
|
||||
for (int i = 0; i < (int)mAudioCommands.size(); i++) {
|
||||
mAudioCommands[i]->dump(buffer, SIZE);
|
||||
result.append(buffer);
|
||||
}
|
||||
result.append(" Last Command\n");
|
||||
mLastCommand.dump(buffer, SIZE);
|
||||
result.append(buffer);
|
||||
|
||||
write(fd, result.string(), result.size());
|
||||
|
||||
if (locked) mLock.unlock();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
|
||||
{
|
||||
AudioCommand *command = new AudioCommand();
|
||||
command->mCommand = START_TONE;
|
||||
ToneData *data = new ToneData();
|
||||
data->mType = type;
|
||||
data->mStream = stream;
|
||||
command->mParam = (void *)data;
|
||||
command->mWaitStatus = false;
|
||||
Mutex::Autolock _l(mLock);
|
||||
insertCommand_l(command);
|
||||
LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
|
||||
void AudioPolicyService::AudioCommandThread::stopToneCommand()
|
||||
{
|
||||
AudioCommand *command = new AudioCommand();
|
||||
command->mCommand = STOP_TONE;
|
||||
command->mParam = NULL;
|
||||
command->mWaitStatus = false;
|
||||
Mutex::Autolock _l(mLock);
|
||||
insertCommand_l(command);
|
||||
LOGV("AudioCommandThread() adding tone stop");
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
|
||||
{
|
||||
status_t status = NO_ERROR;
|
||||
|
||||
AudioCommand *command = new AudioCommand();
|
||||
command->mCommand = SET_VOLUME;
|
||||
VolumeData *data = new VolumeData();
|
||||
data->mStream = stream;
|
||||
data->mVolume = volume;
|
||||
data->mIO = output;
|
||||
command->mParam = data;
|
||||
if (delayMs == 0) {
|
||||
command->mWaitStatus = true;
|
||||
} else {
|
||||
command->mWaitStatus = false;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
insertCommand_l(command, delayMs);
|
||||
LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
|
||||
mWaitWorkCV.signal();
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.wait(mLock);
|
||||
status = command->mStatus;
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
|
||||
{
|
||||
status_t status = NO_ERROR;
|
||||
|
||||
AudioCommand *command = new AudioCommand();
|
||||
command->mCommand = SET_PARAMETERS;
|
||||
ParametersData *data = new ParametersData();
|
||||
data->mIO = ioHandle;
|
||||
data->mKeyValuePairs = keyValuePairs;
|
||||
command->mParam = data;
|
||||
if (delayMs == 0) {
|
||||
command->mWaitStatus = true;
|
||||
} else {
|
||||
command->mWaitStatus = false;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
insertCommand_l(command, delayMs);
|
||||
LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
|
||||
mWaitWorkCV.signal();
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.wait(mLock);
|
||||
status = command->mStatus;
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
|
||||
{
|
||||
status_t status = NO_ERROR;
|
||||
|
||||
AudioCommand *command = new AudioCommand();
|
||||
command->mCommand = SET_VOICE_VOLUME;
|
||||
VoiceVolumeData *data = new VoiceVolumeData();
|
||||
data->mVolume = volume;
|
||||
command->mParam = data;
|
||||
if (delayMs == 0) {
|
||||
command->mWaitStatus = true;
|
||||
} else {
|
||||
command->mWaitStatus = false;
|
||||
}
|
||||
Mutex::Autolock _l(mLock);
|
||||
insertCommand_l(command, delayMs);
|
||||
LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
|
||||
mWaitWorkCV.signal();
|
||||
if (command->mWaitStatus) {
|
||||
command->mCond.wait(mLock);
|
||||
status = command->mStatus;
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// insertCommand_l() must be called with mLock held
|
||||
void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
|
||||
{
|
||||
ssize_t i;
|
||||
Vector <AudioCommand *> removedCommands;
|
||||
|
||||
command->mTime = systemTime() + milliseconds(delayMs);
|
||||
|
||||
// acquire wake lock to make sure delayed commands are processed
|
||||
if (mName != "" && mAudioCommands.isEmpty()) {
|
||||
acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
|
||||
}
|
||||
|
||||
// check same pending commands with later time stamps and eliminate them
|
||||
for (i = mAudioCommands.size()-1; i >= 0; i--) {
|
||||
AudioCommand *command2 = mAudioCommands[i];
|
||||
// commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
|
||||
if (command2->mTime <= command->mTime) break;
|
||||
if (command2->mCommand != command->mCommand) continue;
|
||||
|
||||
switch (command->mCommand) {
|
||||
case SET_PARAMETERS: {
|
||||
ParametersData *data = (ParametersData *)command->mParam;
|
||||
ParametersData *data2 = (ParametersData *)command2->mParam;
|
||||
if (data->mIO != data2->mIO) break;
|
||||
LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
|
||||
AudioParameter param = AudioParameter(data->mKeyValuePairs);
|
||||
AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
|
||||
for (size_t j = 0; j < param.size(); j++) {
|
||||
String8 key;
|
||||
String8 value;
|
||||
param.getAt(j, key, value);
|
||||
for (size_t k = 0; k < param2.size(); k++) {
|
||||
String8 key2;
|
||||
String8 value2;
|
||||
param2.getAt(k, key2, value2);
|
||||
if (key2 == key) {
|
||||
param2.remove(key2);
|
||||
LOGV("Filtering out parameter %s", key2.string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if all keys have been filtered out, remove the command.
|
||||
// otherwise, update the key value pairs
|
||||
if (param2.size() == 0) {
|
||||
removedCommands.add(command2);
|
||||
} else {
|
||||
data2->mKeyValuePairs = param2.toString();
|
||||
}
|
||||
} break;
|
||||
|
||||
case SET_VOLUME: {
|
||||
VolumeData *data = (VolumeData *)command->mParam;
|
||||
VolumeData *data2 = (VolumeData *)command2->mParam;
|
||||
if (data->mIO != data2->mIO) break;
|
||||
if (data->mStream != data2->mStream) break;
|
||||
LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
|
||||
removedCommands.add(command2);
|
||||
} break;
|
||||
case START_TONE:
|
||||
case STOP_TONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove filtered commands
|
||||
for (size_t j = 0; j < removedCommands.size(); j++) {
|
||||
// removed commands always have time stamps greater than current command
|
||||
for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
|
||||
if (mAudioCommands[k] == removedCommands[j]) {
|
||||
LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
|
||||
mAudioCommands.removeAt(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
removedCommands.clear();
|
||||
|
||||
// insert command at the right place according to its time stamp
|
||||
LOGV("inserting command: %d at index %d, num commands %d", command->mCommand, (int)i+1, mAudioCommands.size());
|
||||
mAudioCommands.insertAt(command, i + 1);
|
||||
}
|
||||
|
||||
void AudioPolicyService::AudioCommandThread::exit()
|
||||
{
|
||||
LOGV("AudioCommandThread::exit");
|
||||
{
|
||||
AutoMutex _l(mLock);
|
||||
requestExit();
|
||||
mWaitWorkCV.signal();
|
||||
}
|
||||
requestExitAndWait();
|
||||
}
|
||||
|
||||
void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
|
||||
{
|
||||
snprintf(buffer, size, " %02d %06d.%03d %01u %p\n",
|
||||
mCommand,
|
||||
(int)ns2s(mTime),
|
||||
(int)ns2ms(mTime)%1000,
|
||||
mWaitStatus,
|
||||
mParam);
|
||||
}
|
||||
|
||||
}; // namespace android
|
@ -1,223 +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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_AUDIOPOLICYSERVICE_H
|
||||
#define ANDROID_AUDIOPOLICYSERVICE_H
|
||||
|
||||
#include <media/IAudioPolicyService.h>
|
||||
#include <hardware_legacy/AudioPolicyInterface.h>
|
||||
#include <media/ToneGenerator.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class String8;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioPolicyService: public BnAudioPolicyService, public AudioPolicyClientInterface, public IBinder::DeathRecipient
|
||||
{
|
||||
|
||||
public:
|
||||
static void instantiate();
|
||||
|
||||
virtual status_t dump(int fd, const Vector<String16>& args);
|
||||
|
||||
//
|
||||
// BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
|
||||
//
|
||||
|
||||
virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
|
||||
AudioSystem::device_connection_state state,
|
||||
const char *device_address);
|
||||
virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices 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,
|
||||
uint32_t samplingRate = 0,
|
||||
uint32_t format = AudioSystem::FORMAT_DEFAULT,
|
||||
uint32_t channels = 0,
|
||||
AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT);
|
||||
virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
|
||||
virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
|
||||
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 channels = 0,
|
||||
AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)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,
|
||||
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 onTransact(
|
||||
uint32_t code,
|
||||
const Parcel& data,
|
||||
Parcel* reply,
|
||||
uint32_t flags);
|
||||
|
||||
// IBinder::DeathRecipient
|
||||
virtual void binderDied(const wp<IBinder>& who);
|
||||
|
||||
//
|
||||
// AudioPolicyClientInterface
|
||||
//
|
||||
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, 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 stopTone();
|
||||
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
|
||||
|
||||
private:
|
||||
AudioPolicyService();
|
||||
virtual ~AudioPolicyService();
|
||||
|
||||
status_t dumpInternals(int fd);
|
||||
|
||||
// Thread used for tone playback and to send audio config commands to audio flinger
|
||||
// For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
|
||||
// and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
|
||||
// calls to AudioPolicyService and an attempt to lock mLock.
|
||||
// For audio config commands, it is necessary because audio flinger requires that the calling process (user)
|
||||
// has permission to modify audio settings.
|
||||
class AudioCommandThread : public Thread {
|
||||
class AudioCommand;
|
||||
public:
|
||||
|
||||
// commands for tone AudioCommand
|
||||
enum {
|
||||
START_TONE,
|
||||
STOP_TONE,
|
||||
SET_VOLUME,
|
||||
SET_PARAMETERS,
|
||||
SET_VOICE_VOLUME
|
||||
};
|
||||
|
||||
AudioCommandThread (String8 name);
|
||||
virtual ~AudioCommandThread();
|
||||
|
||||
status_t dump(int fd);
|
||||
|
||||
// Thread virtuals
|
||||
virtual void onFirstRef();
|
||||
virtual bool threadLoop();
|
||||
|
||||
void exit();
|
||||
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 voiceVolumeCommand(float volume, int delayMs = 0);
|
||||
void insertCommand_l(AudioCommand *command, int delayMs = 0);
|
||||
|
||||
private:
|
||||
// descriptor for requested tone playback event
|
||||
class AudioCommand {
|
||||
|
||||
public:
|
||||
AudioCommand()
|
||||
: mCommand(-1) {}
|
||||
|
||||
void dump(char* buffer, size_t size);
|
||||
|
||||
int mCommand; // START_TONE, STOP_TONE ...
|
||||
nsecs_t mTime; // time stamp
|
||||
Condition mCond; // condition for status return
|
||||
status_t mStatus; // command status
|
||||
bool mWaitStatus; // true if caller is waiting for status
|
||||
void *mParam; // command parameter (ToneData, VolumeData, ParametersData)
|
||||
};
|
||||
|
||||
class ToneData {
|
||||
public:
|
||||
int mType; // tone type (START_TONE only)
|
||||
int mStream; // stream type (START_TONE only)
|
||||
};
|
||||
|
||||
class VolumeData {
|
||||
public:
|
||||
int mStream;
|
||||
float mVolume;
|
||||
int mIO;
|
||||
};
|
||||
|
||||
class ParametersData {
|
||||
public:
|
||||
int mIO;
|
||||
String8 mKeyValuePairs;
|
||||
};
|
||||
|
||||
class VoiceVolumeData {
|
||||
public:
|
||||
float mVolume;
|
||||
};
|
||||
|
||||
Mutex mLock;
|
||||
Condition mWaitWorkCV;
|
||||
Vector <AudioCommand *> mAudioCommands; // list of pending commands
|
||||
ToneGenerator *mpToneGenerator; // the tone generator
|
||||
AudioCommand mLastCommand; // last processed command (used by dump)
|
||||
String8 mName; // string used by wake lock fo delayed commands
|
||||
};
|
||||
|
||||
// Internal dump utilities.
|
||||
status_t dumpPermissionDenial(int fd);
|
||||
|
||||
|
||||
Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device
|
||||
// connection stated our routing
|
||||
AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
|
||||
sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
|
||||
sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_AUDIOPOLICYSERVICE_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,595 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AudioResampler"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
#include "AudioResampler.h"
|
||||
#include "AudioResamplerSinc.h"
|
||||
#include "AudioResamplerCubic.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
#ifdef __ARM_ARCH_5E__ // optimized asm option
|
||||
#define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
|
||||
#endif // __ARM_ARCH_5E__
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioResamplerOrder1 : public AudioResampler {
|
||||
public:
|
||||
AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) :
|
||||
AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) {
|
||||
}
|
||||
virtual void resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
private:
|
||||
// number of bits used in interpolation multiply - 15 bits avoids overflow
|
||||
static const int kNumInterpBits = 15;
|
||||
|
||||
// bits to shift the phase fraction down to avoid overflow
|
||||
static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
|
||||
|
||||
void init() {}
|
||||
void resampleMono16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
void resampleStereo16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
|
||||
void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
|
||||
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
|
||||
uint32_t &phaseFraction, uint32_t phaseIncrement);
|
||||
void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
|
||||
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
|
||||
uint32_t &phaseFraction, uint32_t phaseIncrement);
|
||||
#endif // ASM_ARM_RESAMP1
|
||||
|
||||
static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
|
||||
return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
|
||||
}
|
||||
static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
|
||||
*frac += inc;
|
||||
*index += (size_t)(*frac >> kNumPhaseBits);
|
||||
*frac &= kPhaseMask;
|
||||
}
|
||||
int mX0L;
|
||||
int mX0R;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
|
||||
int32_t sampleRate, int quality) {
|
||||
|
||||
// can only create low quality resample now
|
||||
AudioResampler* resampler;
|
||||
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
if (property_get("af.resampler.quality", value, 0)) {
|
||||
quality = atoi(value);
|
||||
LOGD("forcing AudioResampler quality to %d", quality);
|
||||
}
|
||||
|
||||
if (quality == DEFAULT)
|
||||
quality = LOW_QUALITY;
|
||||
|
||||
switch (quality) {
|
||||
default:
|
||||
case LOW_QUALITY:
|
||||
LOGV("Create linear Resampler");
|
||||
resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
|
||||
break;
|
||||
case MED_QUALITY:
|
||||
LOGV("Create cubic Resampler");
|
||||
resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
|
||||
break;
|
||||
case HIGH_QUALITY:
|
||||
LOGV("Create sinc Resampler");
|
||||
resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize resampler
|
||||
resampler->init();
|
||||
return resampler;
|
||||
}
|
||||
|
||||
AudioResampler::AudioResampler(int bitDepth, int inChannelCount,
|
||||
int32_t sampleRate) :
|
||||
mBitDepth(bitDepth), mChannelCount(inChannelCount),
|
||||
mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
|
||||
mPhaseFraction(0) {
|
||||
// sanity check on format
|
||||
if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) {
|
||||
LOGE("Unsupported sample format, %d bits, %d channels", bitDepth,
|
||||
inChannelCount);
|
||||
// LOG_ASSERT(0);
|
||||
}
|
||||
|
||||
// initialize common members
|
||||
mVolume[0] = mVolume[1] = 0;
|
||||
mBuffer.frameCount = 0;
|
||||
|
||||
// save format for quick lookup
|
||||
if (inChannelCount == 1) {
|
||||
mFormat = MONO_16_BIT;
|
||||
} else {
|
||||
mFormat = STEREO_16_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
AudioResampler::~AudioResampler() {
|
||||
}
|
||||
|
||||
void AudioResampler::setSampleRate(int32_t inSampleRate) {
|
||||
mInSampleRate = inSampleRate;
|
||||
mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
|
||||
}
|
||||
|
||||
void AudioResampler::setVolume(int16_t left, int16_t right) {
|
||||
// TODO: Implement anti-zipper filter
|
||||
mVolume[0] = left;
|
||||
mVolume[1] = right;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
// should never happen, but we overflow if it does
|
||||
// LOG_ASSERT(outFrameCount < 32767);
|
||||
|
||||
// select the appropriate resampler
|
||||
switch (mChannelCount) {
|
||||
case 1:
|
||||
resampleMono16(out, outFrameCount, provider);
|
||||
break;
|
||||
case 2:
|
||||
resampleStereo16(out, outFrameCount, provider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
int32_t vl = mVolume[0];
|
||||
int32_t vr = mVolume[1];
|
||||
|
||||
size_t inputIndex = mInputIndex;
|
||||
uint32_t phaseFraction = mPhaseFraction;
|
||||
uint32_t phaseIncrement = mPhaseIncrement;
|
||||
size_t outputIndex = 0;
|
||||
size_t outputSampleCount = outFrameCount * 2;
|
||||
size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
|
||||
|
||||
// LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
|
||||
// outFrameCount, inputIndex, phaseFraction, phaseIncrement);
|
||||
|
||||
while (outputIndex < outputSampleCount) {
|
||||
|
||||
// buffer is empty, fetch a new one
|
||||
while (mBuffer.frameCount == 0) {
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL) {
|
||||
goto resampleStereo16_exit;
|
||||
}
|
||||
|
||||
// LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
|
||||
if (mBuffer.frameCount > inputIndex) break;
|
||||
|
||||
inputIndex -= mBuffer.frameCount;
|
||||
mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
|
||||
mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
// mBuffer.frameCount == 0 now so we reload a new buffer
|
||||
}
|
||||
|
||||
int16_t *in = mBuffer.i16;
|
||||
|
||||
// handle boundary case
|
||||
while (inputIndex == 0) {
|
||||
// LOGE("boundary case\n");
|
||||
out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
|
||||
out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
|
||||
Advance(&inputIndex, &phaseFraction, phaseIncrement);
|
||||
if (outputIndex == outputSampleCount)
|
||||
break;
|
||||
}
|
||||
|
||||
// process input samples
|
||||
// LOGE("general case\n");
|
||||
|
||||
#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
|
||||
if (inputIndex + 2 < mBuffer.frameCount) {
|
||||
int32_t* maxOutPt;
|
||||
int32_t maxInIdx;
|
||||
|
||||
maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop
|
||||
maxInIdx = mBuffer.frameCount - 2;
|
||||
AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
|
||||
phaseFraction, phaseIncrement);
|
||||
}
|
||||
#endif // ASM_ARM_RESAMP1
|
||||
|
||||
while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
|
||||
out[outputIndex++] += vl * Interp(in[inputIndex*2-2],
|
||||
in[inputIndex*2], phaseFraction);
|
||||
out[outputIndex++] += vr * Interp(in[inputIndex*2-1],
|
||||
in[inputIndex*2+1], phaseFraction);
|
||||
Advance(&inputIndex, &phaseFraction, phaseIncrement);
|
||||
}
|
||||
|
||||
// LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
|
||||
|
||||
// if done with buffer, save samples
|
||||
if (inputIndex >= mBuffer.frameCount) {
|
||||
inputIndex -= mBuffer.frameCount;
|
||||
|
||||
// LOGE("buffer done, new input index %d", inputIndex);
|
||||
|
||||
mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
|
||||
mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
|
||||
// verify that the releaseBuffer resets the buffer frameCount
|
||||
// LOG_ASSERT(mBuffer.frameCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
|
||||
|
||||
resampleStereo16_exit:
|
||||
// save state
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
}
|
||||
|
||||
void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
int32_t vl = mVolume[0];
|
||||
int32_t vr = mVolume[1];
|
||||
|
||||
size_t inputIndex = mInputIndex;
|
||||
uint32_t phaseFraction = mPhaseFraction;
|
||||
uint32_t phaseIncrement = mPhaseIncrement;
|
||||
size_t outputIndex = 0;
|
||||
size_t outputSampleCount = outFrameCount * 2;
|
||||
size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
|
||||
|
||||
// LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
|
||||
// outFrameCount, inputIndex, phaseFraction, phaseIncrement);
|
||||
while (outputIndex < outputSampleCount) {
|
||||
// buffer is empty, fetch a new one
|
||||
while (mBuffer.frameCount == 0) {
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL) {
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
goto resampleMono16_exit;
|
||||
}
|
||||
// LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
|
||||
if (mBuffer.frameCount > inputIndex) break;
|
||||
|
||||
inputIndex -= mBuffer.frameCount;
|
||||
mX0L = mBuffer.i16[mBuffer.frameCount-1];
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
// mBuffer.frameCount == 0 now so we reload a new buffer
|
||||
}
|
||||
int16_t *in = mBuffer.i16;
|
||||
|
||||
// handle boundary case
|
||||
while (inputIndex == 0) {
|
||||
// LOGE("boundary case\n");
|
||||
int32_t sample = Interp(mX0L, in[0], phaseFraction);
|
||||
out[outputIndex++] += vl * sample;
|
||||
out[outputIndex++] += vr * sample;
|
||||
Advance(&inputIndex, &phaseFraction, phaseIncrement);
|
||||
if (outputIndex == outputSampleCount)
|
||||
break;
|
||||
}
|
||||
|
||||
// process input samples
|
||||
// LOGE("general case\n");
|
||||
|
||||
#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
|
||||
if (inputIndex + 2 < mBuffer.frameCount) {
|
||||
int32_t* maxOutPt;
|
||||
int32_t maxInIdx;
|
||||
|
||||
maxOutPt = out + (outputSampleCount - 2);
|
||||
maxInIdx = (int32_t)mBuffer.frameCount - 2;
|
||||
AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
|
||||
phaseFraction, phaseIncrement);
|
||||
}
|
||||
#endif // ASM_ARM_RESAMP1
|
||||
|
||||
while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
|
||||
int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
|
||||
phaseFraction);
|
||||
out[outputIndex++] += vl * sample;
|
||||
out[outputIndex++] += vr * sample;
|
||||
Advance(&inputIndex, &phaseFraction, phaseIncrement);
|
||||
}
|
||||
|
||||
|
||||
// LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
|
||||
|
||||
// if done with buffer, save samples
|
||||
if (inputIndex >= mBuffer.frameCount) {
|
||||
inputIndex -= mBuffer.frameCount;
|
||||
|
||||
// LOGE("buffer done, new input index %d", inputIndex);
|
||||
|
||||
mX0L = mBuffer.i16[mBuffer.frameCount-1];
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
|
||||
// verify that the releaseBuffer resets the buffer frameCount
|
||||
// LOG_ASSERT(mBuffer.frameCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
|
||||
|
||||
resampleMono16_exit:
|
||||
// save state
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
}
|
||||
|
||||
#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* AsmMono16Loop
|
||||
* asm optimized monotonic loop version; one loop is 2 frames
|
||||
* Input:
|
||||
* in : pointer on input samples
|
||||
* maxOutPt : pointer on first not filled
|
||||
* maxInIdx : index on first not used
|
||||
* outputIndex : pointer on current output index
|
||||
* out : pointer on output buffer
|
||||
* inputIndex : pointer on current input index
|
||||
* vl, vr : left and right gain
|
||||
* phaseFraction : pointer on current phase fraction
|
||||
* phaseIncrement
|
||||
* Ouput:
|
||||
* outputIndex :
|
||||
* out : updated buffer
|
||||
* inputIndex : index of next to use
|
||||
* phaseFraction : phase fraction for next interpolation
|
||||
*
|
||||
*******************************************************************/
|
||||
void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
|
||||
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
|
||||
uint32_t &phaseFraction, uint32_t phaseIncrement)
|
||||
{
|
||||
#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex)
|
||||
|
||||
asm(
|
||||
"stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||
// get parameters
|
||||
" ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
|
||||
" ldr r6, [r6]\n" // phaseFraction
|
||||
" ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
|
||||
" ldr r7, [r7]\n" // inputIndex
|
||||
" ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out
|
||||
" ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
|
||||
" ldr r0, [r0]\n" // outputIndex
|
||||
" add r8, r0, asl #2\n" // curOut
|
||||
" ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement
|
||||
" ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl
|
||||
" ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr
|
||||
|
||||
// r0 pin, x0, Samp
|
||||
|
||||
// r1 in
|
||||
// r2 maxOutPt
|
||||
// r3 maxInIdx
|
||||
|
||||
// r4 x1, i1, i3, Out1
|
||||
// r5 out0
|
||||
|
||||
// r6 frac
|
||||
// r7 inputIndex
|
||||
// r8 curOut
|
||||
|
||||
// r9 inc
|
||||
// r10 vl
|
||||
// r11 vr
|
||||
|
||||
// r12
|
||||
// r13 sp
|
||||
// r14
|
||||
|
||||
// the following loop works on 2 frames
|
||||
|
||||
".Y4L01:\n"
|
||||
" cmp r8, r2\n" // curOut - maxCurOut
|
||||
" bcs .Y4L02\n"
|
||||
|
||||
#define MO_ONE_FRAME \
|
||||
" add r0, r1, r7, asl #1\n" /* in + inputIndex */\
|
||||
" ldrsh r4, [r0]\n" /* in[inputIndex] */\
|
||||
" ldr r5, [r8]\n" /* out[outputIndex] */\
|
||||
" ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\
|
||||
" bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
|
||||
" sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\
|
||||
" mov r4, r4, lsl #2\n" /* <<2 */\
|
||||
" smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
|
||||
" add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
|
||||
" add r0, r0, r4\n" /* x0 - (..) */\
|
||||
" mla r5, r0, r10, r5\n" /* vl*interp + out[] */\
|
||||
" ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
|
||||
" str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
|
||||
" mla r4, r0, r11, r4\n" /* vr*interp + out[] */\
|
||||
" add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\
|
||||
" str r4, [r8], #4\n" /* out[outputIndex++] = ... */
|
||||
|
||||
MO_ONE_FRAME // frame 1
|
||||
MO_ONE_FRAME // frame 2
|
||||
|
||||
" cmp r7, r3\n" // inputIndex - maxInIdx
|
||||
" bcc .Y4L01\n"
|
||||
".Y4L02:\n"
|
||||
|
||||
" bic r6, r6, #0xC0000000\n" // phaseFraction & ...
|
||||
// save modified values
|
||||
" ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
|
||||
" str r6, [r0]\n" // phaseFraction
|
||||
" ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
|
||||
" str r7, [r0]\n" // inputIndex
|
||||
" ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out
|
||||
" sub r8, r0\n" // curOut - out
|
||||
" asr r8, #2\n" // new outputIndex
|
||||
" ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
|
||||
" str r8, [r0]\n" // save outputIndex
|
||||
|
||||
" ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
|
||||
);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* AsmStereo16Loop
|
||||
* asm optimized stereo loop version; one loop is 2 frames
|
||||
* Input:
|
||||
* in : pointer on input samples
|
||||
* maxOutPt : pointer on first not filled
|
||||
* maxInIdx : index on first not used
|
||||
* outputIndex : pointer on current output index
|
||||
* out : pointer on output buffer
|
||||
* inputIndex : pointer on current input index
|
||||
* vl, vr : left and right gain
|
||||
* phaseFraction : pointer on current phase fraction
|
||||
* phaseIncrement
|
||||
* Ouput:
|
||||
* outputIndex :
|
||||
* out : updated buffer
|
||||
* inputIndex : index of next to use
|
||||
* phaseFraction : phase fraction for next interpolation
|
||||
*
|
||||
*******************************************************************/
|
||||
void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
|
||||
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
|
||||
uint32_t &phaseFraction, uint32_t phaseIncrement)
|
||||
{
|
||||
#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex)
|
||||
asm(
|
||||
"stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
|
||||
// get parameters
|
||||
" ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
|
||||
" ldr r6, [r6]\n" // phaseFraction
|
||||
" ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
|
||||
" ldr r7, [r7]\n" // inputIndex
|
||||
" ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out
|
||||
" ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
|
||||
" ldr r0, [r0]\n" // outputIndex
|
||||
" add r8, r0, asl #2\n" // curOut
|
||||
" ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement
|
||||
" ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl
|
||||
" ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr
|
||||
|
||||
// r0 pin, x0, Samp
|
||||
|
||||
// r1 in
|
||||
// r2 maxOutPt
|
||||
// r3 maxInIdx
|
||||
|
||||
// r4 x1, i1, i3, out1
|
||||
// r5 out0
|
||||
|
||||
// r6 frac
|
||||
// r7 inputIndex
|
||||
// r8 curOut
|
||||
|
||||
// r9 inc
|
||||
// r10 vl
|
||||
// r11 vr
|
||||
|
||||
// r12 temporary
|
||||
// r13 sp
|
||||
// r14
|
||||
|
||||
".Y5L01:\n"
|
||||
" cmp r8, r2\n" // curOut - maxCurOut
|
||||
" bcs .Y5L02\n"
|
||||
|
||||
#define ST_ONE_FRAME \
|
||||
" bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
|
||||
\
|
||||
" add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\
|
||||
\
|
||||
" ldrsh r4, [r0]\n" /* in[2*inputIndex] */\
|
||||
" ldr r5, [r8]\n" /* out[outputIndex] */\
|
||||
" ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\
|
||||
" sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
|
||||
" mov r4, r4, lsl #2\n" /* <<2 */\
|
||||
" smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
|
||||
" add r12, r12, r4\n" /* x0 - (..) */\
|
||||
" mla r5, r12, r10, r5\n" /* vl*interp + out[] */\
|
||||
" ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
|
||||
" str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
|
||||
\
|
||||
" ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\
|
||||
" ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\
|
||||
" sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
|
||||
" mov r12, r12, lsl #2\n" /* <<2 */\
|
||||
" smulwt r12, r12, r6\n" /* (x1-x0)*.. */\
|
||||
" add r12, r0, r12\n" /* x0 - (..) */\
|
||||
" mla r4, r12, r11, r4\n" /* vr*interp + out[] */\
|
||||
" str r4, [r8], #4\n" /* out[outputIndex++] = ... */\
|
||||
\
|
||||
" add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
|
||||
" add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */
|
||||
|
||||
ST_ONE_FRAME // frame 1
|
||||
ST_ONE_FRAME // frame 1
|
||||
|
||||
" cmp r7, r3\n" // inputIndex - maxInIdx
|
||||
" bcc .Y5L01\n"
|
||||
".Y5L02:\n"
|
||||
|
||||
" bic r6, r6, #0xC0000000\n" // phaseFraction & ...
|
||||
// save modified values
|
||||
" ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
|
||||
" str r6, [r0]\n" // phaseFraction
|
||||
" ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
|
||||
" str r7, [r0]\n" // inputIndex
|
||||
" ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out
|
||||
" sub r8, r0\n" // curOut - out
|
||||
" asr r8, #2\n" // new outputIndex
|
||||
" ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
|
||||
" str r8, [r0]\n" // save outputIndex
|
||||
|
||||
" ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n"
|
||||
);
|
||||
}
|
||||
|
||||
#endif // ASM_ARM_RESAMP1
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
||||
; // namespace android
|
||||
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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_RESAMPLER_H
|
||||
#define ANDROID_AUDIO_RESAMPLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "AudioBufferProvider.h"
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioResampler {
|
||||
public:
|
||||
// Determines quality of SRC.
|
||||
// LOW_QUALITY: linear interpolator (1st order)
|
||||
// MED_QUALITY: cubic interpolator (3rd order)
|
||||
// HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
|
||||
// NOTE: high quality SRC will only be supported for
|
||||
// certain fixed rate conversions. Sample rate cannot be
|
||||
// changed dynamically.
|
||||
enum src_quality {
|
||||
DEFAULT=0,
|
||||
LOW_QUALITY=1,
|
||||
MED_QUALITY=2,
|
||||
HIGH_QUALITY=3
|
||||
};
|
||||
|
||||
static AudioResampler* create(int bitDepth, int inChannelCount,
|
||||
int32_t sampleRate, int quality=DEFAULT);
|
||||
|
||||
virtual ~AudioResampler();
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void setSampleRate(int32_t inSampleRate);
|
||||
virtual void setVolume(int16_t left, int16_t right);
|
||||
|
||||
virtual void resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) = 0;
|
||||
|
||||
protected:
|
||||
// number of bits for phase fraction - 30 bits allows nearly 2x downsampling
|
||||
static const int kNumPhaseBits = 30;
|
||||
|
||||
// phase mask for fraction
|
||||
static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
|
||||
|
||||
// multiplier to calculate fixed point phase increment
|
||||
static const double kPhaseMultiplier = 1L << kNumPhaseBits;
|
||||
|
||||
enum format {MONO_16_BIT, STEREO_16_BIT};
|
||||
AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate);
|
||||
|
||||
// prevent copying
|
||||
AudioResampler(const AudioResampler&);
|
||||
AudioResampler& operator=(const AudioResampler&);
|
||||
|
||||
int32_t mBitDepth;
|
||||
int32_t mChannelCount;
|
||||
int32_t mSampleRate;
|
||||
int32_t mInSampleRate;
|
||||
AudioBufferProvider::Buffer mBuffer;
|
||||
union {
|
||||
int16_t mVolume[2];
|
||||
uint32_t mVolumeRL;
|
||||
};
|
||||
int16_t mTargetVolume[2];
|
||||
format mFormat;
|
||||
size_t mInputIndex;
|
||||
int32_t mPhaseIncrement;
|
||||
uint32_t mPhaseFraction;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
||||
; // namespace android
|
||||
|
||||
#endif // ANDROID_AUDIO_RESAMPLER_H
|
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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 <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "AudioResampler.h"
|
||||
#include "AudioResamplerCubic.h"
|
||||
|
||||
#define LOG_TAG "AudioSRC"
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void AudioResamplerCubic::init() {
|
||||
memset(&left, 0, sizeof(state));
|
||||
memset(&right, 0, sizeof(state));
|
||||
}
|
||||
|
||||
void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
// should never happen, but we overflow if it does
|
||||
// LOG_ASSERT(outFrameCount < 32767);
|
||||
|
||||
// select the appropriate resampler
|
||||
switch (mChannelCount) {
|
||||
case 1:
|
||||
resampleMono16(out, outFrameCount, provider);
|
||||
break;
|
||||
case 2:
|
||||
resampleStereo16(out, outFrameCount, provider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
int32_t vl = mVolume[0];
|
||||
int32_t vr = mVolume[1];
|
||||
|
||||
size_t inputIndex = mInputIndex;
|
||||
uint32_t phaseFraction = mPhaseFraction;
|
||||
uint32_t phaseIncrement = mPhaseIncrement;
|
||||
size_t outputIndex = 0;
|
||||
size_t outputSampleCount = outFrameCount * 2;
|
||||
size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
|
||||
|
||||
// fetch first buffer
|
||||
if (mBuffer.frameCount == 0) {
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL)
|
||||
return;
|
||||
// LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
|
||||
}
|
||||
int16_t *in = mBuffer.i16;
|
||||
|
||||
while (outputIndex < outputSampleCount) {
|
||||
int32_t sample;
|
||||
int32_t x;
|
||||
|
||||
// calculate output sample
|
||||
x = phaseFraction >> kPreInterpShift;
|
||||
out[outputIndex++] += vl * interp(&left, x);
|
||||
out[outputIndex++] += vr * interp(&right, x);
|
||||
// out[outputIndex++] += vr * in[inputIndex*2];
|
||||
|
||||
// increment phase
|
||||
phaseFraction += phaseIncrement;
|
||||
uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
|
||||
phaseFraction &= kPhaseMask;
|
||||
|
||||
// time to fetch another sample
|
||||
while (indexIncrement--) {
|
||||
|
||||
inputIndex++;
|
||||
if (inputIndex == mBuffer.frameCount) {
|
||||
inputIndex = 0;
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL)
|
||||
goto save_state; // ugly, but efficient
|
||||
in = mBuffer.i16;
|
||||
// LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
|
||||
}
|
||||
|
||||
// advance sample state
|
||||
advance(&left, in[inputIndex*2]);
|
||||
advance(&right, in[inputIndex*2+1]);
|
||||
}
|
||||
}
|
||||
|
||||
save_state:
|
||||
// LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
}
|
||||
|
||||
void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider) {
|
||||
|
||||
int32_t vl = mVolume[0];
|
||||
int32_t vr = mVolume[1];
|
||||
|
||||
size_t inputIndex = mInputIndex;
|
||||
uint32_t phaseFraction = mPhaseFraction;
|
||||
uint32_t phaseIncrement = mPhaseIncrement;
|
||||
size_t outputIndex = 0;
|
||||
size_t outputSampleCount = outFrameCount * 2;
|
||||
size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
|
||||
|
||||
// fetch first buffer
|
||||
if (mBuffer.frameCount == 0) {
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL)
|
||||
return;
|
||||
// LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
|
||||
}
|
||||
int16_t *in = mBuffer.i16;
|
||||
|
||||
while (outputIndex < outputSampleCount) {
|
||||
int32_t sample;
|
||||
int32_t x;
|
||||
|
||||
// calculate output sample
|
||||
x = phaseFraction >> kPreInterpShift;
|
||||
sample = interp(&left, x);
|
||||
out[outputIndex++] += vl * sample;
|
||||
out[outputIndex++] += vr * sample;
|
||||
|
||||
// increment phase
|
||||
phaseFraction += phaseIncrement;
|
||||
uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
|
||||
phaseFraction &= kPhaseMask;
|
||||
|
||||
// time to fetch another sample
|
||||
while (indexIncrement--) {
|
||||
|
||||
inputIndex++;
|
||||
if (inputIndex == mBuffer.frameCount) {
|
||||
inputIndex = 0;
|
||||
provider->releaseBuffer(&mBuffer);
|
||||
mBuffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&mBuffer);
|
||||
if (mBuffer.raw == NULL)
|
||||
goto save_state; // ugly, but efficient
|
||||
// LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
|
||||
in = mBuffer.i16;
|
||||
}
|
||||
|
||||
// advance sample state
|
||||
advance(&left, in[inputIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
save_state:
|
||||
// LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
||||
; // namespace android
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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_RESAMPLER_CUBIC_H
|
||||
#define ANDROID_AUDIO_RESAMPLER_CUBIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "AudioResampler.h"
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioResamplerCubic : public AudioResampler {
|
||||
public:
|
||||
AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) :
|
||||
AudioResampler(bitDepth, inChannelCount, sampleRate) {
|
||||
}
|
||||
virtual void resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
private:
|
||||
// number of bits used in interpolation multiply - 14 bits avoids overflow
|
||||
static const int kNumInterpBits = 14;
|
||||
|
||||
// bits to shift the phase fraction down to avoid overflow
|
||||
static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
|
||||
typedef struct {
|
||||
int32_t a, b, c, y0, y1, y2, y3;
|
||||
} state;
|
||||
void init();
|
||||
void resampleMono16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
void resampleStereo16(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
static inline int32_t interp(state* p, int32_t x) {
|
||||
return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1;
|
||||
}
|
||||
static inline void advance(state* p, int16_t in) {
|
||||
p->y0 = p->y1;
|
||||
p->y1 = p->y2;
|
||||
p->y2 = p->y3;
|
||||
p->y3 = in;
|
||||
p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1;
|
||||
p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1);
|
||||
p->c = (p->y2 - p->y0) >> 1;
|
||||
}
|
||||
state left, right;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/
|
@ -1,358 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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 <string.h>
|
||||
#include "AudioResamplerSinc.h"
|
||||
|
||||
namespace android {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
* These coeficients are computed with the "fir" utility found in
|
||||
* tools/resampler_tools
|
||||
* TODO: A good optimization would be to transpose this matrix, to take
|
||||
* better advantage of the data-cache.
|
||||
*/
|
||||
const int32_t AudioResamplerSinc::mFirCoefsUp[] = {
|
||||
0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621,
|
||||
0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9,
|
||||
0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9,
|
||||
0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798,
|
||||
0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636,
|
||||
0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2,
|
||||
0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070,
|
||||
0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000 // this one is needed for lerping the last coefficient
|
||||
};
|
||||
|
||||
/*
|
||||
* These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz)
|
||||
* It's possible to use the above coefficient for any down-sampling
|
||||
* at the expense of a slower processing loop (we can interpolate
|
||||
* these coefficient from the above by "Stretching" them in time).
|
||||
*/
|
||||
const int32_t AudioResamplerSinc::mFirCoefsDown[] = {
|
||||
0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540,
|
||||
0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4,
|
||||
0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa,
|
||||
0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066,
|
||||
0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf,
|
||||
0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d,
|
||||
0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a,
|
||||
0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000,
|
||||
0x00000000 // this one is needed for lerping the last coefficient
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static inline
|
||||
int32_t mulRL(int left, int32_t in, uint32_t vRL)
|
||||
{
|
||||
#if defined(__arm__) && !defined(__thumb__)
|
||||
int32_t out;
|
||||
if (left) {
|
||||
asm( "smultb %[out], %[in], %[vRL] \n"
|
||||
: [out]"=r"(out)
|
||||
: [in]"%r"(in), [vRL]"r"(vRL)
|
||||
: );
|
||||
} else {
|
||||
asm( "smultt %[out], %[in], %[vRL] \n"
|
||||
: [out]"=r"(out)
|
||||
: [in]"%r"(in), [vRL]"r"(vRL)
|
||||
: );
|
||||
}
|
||||
return out;
|
||||
#else
|
||||
if (left) {
|
||||
return int16_t(in>>16) * int16_t(vRL&0xFFFF);
|
||||
} else {
|
||||
return int16_t(in>>16) * int16_t(vRL>>16);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline
|
||||
int32_t mulAdd(int16_t in, int32_t v, int32_t a)
|
||||
{
|
||||
#if defined(__arm__) && !defined(__thumb__)
|
||||
int32_t out;
|
||||
asm( "smlawb %[out], %[v], %[in], %[a] \n"
|
||||
: [out]"=r"(out)
|
||||
: [in]"%r"(in), [v]"r"(v), [a]"r"(a)
|
||||
: );
|
||||
return out;
|
||||
#else
|
||||
return a + in * (v>>16);
|
||||
// improved precision
|
||||
// return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline
|
||||
int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
|
||||
{
|
||||
#if defined(__arm__) && !defined(__thumb__)
|
||||
int32_t out;
|
||||
if (left) {
|
||||
asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
|
||||
: [out]"=r"(out)
|
||||
: [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
|
||||
: );
|
||||
} else {
|
||||
asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
|
||||
: [out]"=r"(out)
|
||||
: [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
|
||||
: );
|
||||
}
|
||||
return out;
|
||||
#else
|
||||
if (left) {
|
||||
return a + (int16_t(inRL&0xFFFF) * (v>>16));
|
||||
//improved precision
|
||||
// return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16);
|
||||
} else {
|
||||
return a + (int16_t(inRL>>16) * (v>>16));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AudioResamplerSinc::AudioResamplerSinc(int bitDepth,
|
||||
int inChannelCount, int32_t sampleRate)
|
||||
: AudioResampler(bitDepth, inChannelCount, sampleRate),
|
||||
mState(0)
|
||||
{
|
||||
/*
|
||||
* Layout of the state buffer for 32 tap:
|
||||
*
|
||||
* "present" sample beginning of 2nd buffer
|
||||
* v v
|
||||
* 0 01 2 23 3
|
||||
* 0 F0 0 F0 F
|
||||
* [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn]
|
||||
* ^ ^ head
|
||||
*
|
||||
* p = past samples, convoluted with the (p)ositive side of sinc()
|
||||
* n = future samples, convoluted with the (n)egative side of sinc()
|
||||
* r = extra space for implementing the ring buffer
|
||||
*
|
||||
*/
|
||||
|
||||
const size_t numCoefs = 2*halfNumCoefs;
|
||||
const size_t stateSize = numCoefs * inChannelCount * 2;
|
||||
mState = new int16_t[stateSize];
|
||||
memset(mState, 0, sizeof(int16_t)*stateSize);
|
||||
mImpulse = mState + (halfNumCoefs-1)*inChannelCount;
|
||||
mRingFull = mImpulse + (numCoefs+1)*inChannelCount;
|
||||
}
|
||||
|
||||
AudioResamplerSinc::~AudioResamplerSinc()
|
||||
{
|
||||
delete [] mState;
|
||||
}
|
||||
|
||||
void AudioResamplerSinc::init() {
|
||||
}
|
||||
|
||||
void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider)
|
||||
{
|
||||
mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
|
||||
|
||||
// select the appropriate resampler
|
||||
switch (mChannelCount) {
|
||||
case 1:
|
||||
resample<1>(out, outFrameCount, provider);
|
||||
break;
|
||||
case 2:
|
||||
resample<2>(out, outFrameCount, provider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<int CHANNELS>
|
||||
void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider)
|
||||
{
|
||||
int16_t* impulse = mImpulse;
|
||||
uint32_t vRL = mVolumeRL;
|
||||
size_t inputIndex = mInputIndex;
|
||||
uint32_t phaseFraction = mPhaseFraction;
|
||||
uint32_t phaseIncrement = mPhaseIncrement;
|
||||
size_t outputIndex = 0;
|
||||
size_t outputSampleCount = outFrameCount * 2;
|
||||
size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
|
||||
|
||||
AudioBufferProvider::Buffer& buffer(mBuffer);
|
||||
while (outputIndex < outputSampleCount) {
|
||||
// buffer is empty, fetch a new one
|
||||
while (buffer.frameCount == 0) {
|
||||
buffer.frameCount = inFrameCount;
|
||||
provider->getNextBuffer(&buffer);
|
||||
if (buffer.raw == NULL) {
|
||||
goto resample_exit;
|
||||
}
|
||||
const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
|
||||
if (phaseIndex == 1) {
|
||||
// read one frame
|
||||
read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
|
||||
} else if (phaseIndex == 2) {
|
||||
// read 2 frames
|
||||
read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
|
||||
inputIndex++;
|
||||
if (inputIndex >= mBuffer.frameCount) {
|
||||
inputIndex -= mBuffer.frameCount;
|
||||
provider->releaseBuffer(&buffer);
|
||||
} else {
|
||||
read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
int16_t *in = buffer.i16;
|
||||
const size_t frameCount = buffer.frameCount;
|
||||
|
||||
// Always read-in the first samples from the input buffer
|
||||
int16_t* head = impulse + halfNumCoefs*CHANNELS;
|
||||
head[0] = in[inputIndex*CHANNELS + 0];
|
||||
if (CHANNELS == 2)
|
||||
head[1] = in[inputIndex*CHANNELS + 1];
|
||||
|
||||
// handle boundary case
|
||||
int32_t l, r;
|
||||
while (outputIndex < outputSampleCount) {
|
||||
filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse);
|
||||
out[outputIndex++] += 2 * mulRL(1, l, vRL);
|
||||
out[outputIndex++] += 2 * mulRL(0, r, vRL);
|
||||
|
||||
phaseFraction += phaseIncrement;
|
||||
const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
|
||||
if (phaseIndex == 1) {
|
||||
inputIndex++;
|
||||
if (inputIndex >= frameCount)
|
||||
break; // need a new buffer
|
||||
read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
|
||||
} else if(phaseIndex == 2) { // maximum value
|
||||
inputIndex++;
|
||||
if (inputIndex >= frameCount)
|
||||
break; // 0 frame available, 2 frames needed
|
||||
// read first frame
|
||||
read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
|
||||
inputIndex++;
|
||||
if (inputIndex >= frameCount)
|
||||
break; // 0 frame available, 1 frame needed
|
||||
// read second frame
|
||||
read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// if done with buffer, save samples
|
||||
if (inputIndex >= frameCount) {
|
||||
inputIndex -= frameCount;
|
||||
provider->releaseBuffer(&buffer);
|
||||
}
|
||||
}
|
||||
|
||||
resample_exit:
|
||||
mImpulse = impulse;
|
||||
mInputIndex = inputIndex;
|
||||
mPhaseFraction = phaseFraction;
|
||||
}
|
||||
|
||||
template<int CHANNELS>
|
||||
/***
|
||||
* read()
|
||||
*
|
||||
* This function reads only one frame from input buffer and writes it in
|
||||
* state buffer
|
||||
*
|
||||
**/
|
||||
void AudioResamplerSinc::read(
|
||||
int16_t*& impulse, uint32_t& phaseFraction,
|
||||
int16_t const* in, size_t inputIndex)
|
||||
{
|
||||
const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
|
||||
impulse += CHANNELS;
|
||||
phaseFraction -= 1LU<<kNumPhaseBits;
|
||||
if (impulse >= mRingFull) {
|
||||
const size_t stateSize = (halfNumCoefs*2)*CHANNELS;
|
||||
memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize);
|
||||
impulse -= stateSize;
|
||||
}
|
||||
int16_t* head = impulse + halfNumCoefs*CHANNELS;
|
||||
head[0] = in[inputIndex*CHANNELS + 0];
|
||||
if (CHANNELS == 2)
|
||||
head[1] = in[inputIndex*CHANNELS + 1];
|
||||
}
|
||||
|
||||
template<int CHANNELS>
|
||||
void AudioResamplerSinc::filterCoefficient(
|
||||
int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples)
|
||||
{
|
||||
// compute the index of the coefficient on the positive side and
|
||||
// negative side
|
||||
uint32_t indexP = (phase & cMask) >> cShift;
|
||||
uint16_t lerpP = (phase & pMask) >> pShift;
|
||||
uint32_t indexN = (-phase & cMask) >> cShift;
|
||||
uint16_t lerpN = (-phase & pMask) >> pShift;
|
||||
if ((indexP == 0) && (lerpP == 0)) {
|
||||
indexN = cMask >> cShift;
|
||||
lerpN = pMask >> pShift;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
r = 0;
|
||||
int32_t const* coefs = mFirCoefs;
|
||||
int16_t const *sP = samples;
|
||||
int16_t const *sN = samples+CHANNELS;
|
||||
for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) {
|
||||
interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
|
||||
interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
|
||||
sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
|
||||
interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
|
||||
interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
|
||||
sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
|
||||
interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
|
||||
interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
|
||||
sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
|
||||
interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
|
||||
interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
|
||||
sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
|
||||
}
|
||||
}
|
||||
|
||||
template<int CHANNELS>
|
||||
void AudioResamplerSinc::interpolate(
|
||||
int32_t& l, int32_t& r,
|
||||
int32_t const* coefs, int16_t lerp, int16_t const* samples)
|
||||
{
|
||||
int32_t c0 = coefs[0];
|
||||
int32_t c1 = coefs[1];
|
||||
int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0);
|
||||
if (CHANNELS == 2) {
|
||||
uint32_t rl = *reinterpret_cast<uint32_t const*>(samples);
|
||||
l = mulAddRL(1, rl, sinc, l);
|
||||
r = mulAddRL(0, rl, sinc, r);
|
||||
} else {
|
||||
r = l = mulAdd(samples[0], sinc, l);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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_RESAMPLER_SINC_H
|
||||
#define ANDROID_AUDIO_RESAMPLER_SINC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "AudioResampler.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class AudioResamplerSinc : public AudioResampler {
|
||||
public:
|
||||
AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate);
|
||||
|
||||
~AudioResamplerSinc();
|
||||
|
||||
virtual void resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
private:
|
||||
void init();
|
||||
|
||||
template<int CHANNELS>
|
||||
void resample(int32_t* out, size_t outFrameCount,
|
||||
AudioBufferProvider* provider);
|
||||
|
||||
template<int CHANNELS>
|
||||
inline void filterCoefficient(
|
||||
int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples);
|
||||
|
||||
template<int CHANNELS>
|
||||
inline void interpolate(
|
||||
int32_t& l, int32_t& r,
|
||||
int32_t const* coefs, int16_t lerp, int16_t const* samples);
|
||||
|
||||
template<int CHANNELS>
|
||||
inline void read(int16_t*& impulse, uint32_t& phaseFraction,
|
||||
int16_t const* in, size_t inputIndex);
|
||||
|
||||
int16_t *mState;
|
||||
int16_t *mImpulse;
|
||||
int16_t *mRingFull;
|
||||
|
||||
int32_t const * mFirCoefs;
|
||||
static const int32_t mFirCoefsDown[];
|
||||
static const int32_t mFirCoefsUp[];
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static const int32_t RESAMPLE_FIR_NUM_COEF = 8;
|
||||
static const int32_t RESAMPLE_FIR_LERP_INT_BITS = 4;
|
||||
|
||||
// we have 16 coefs samples per zero-crossing
|
||||
static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS; // 4
|
||||
static const int cShift = kNumPhaseBits - coefsBits; // 26
|
||||
static const uint32_t cMask = ((1<<coefsBits)-1) << cShift; // 0xf<<26 = 3c00 0000
|
||||
|
||||
// and we use 15 bits to interpolate between these samples
|
||||
// this cannot change because the mul below rely on it.
|
||||
static const int pLerpBits = 15;
|
||||
static const int pShift = kNumPhaseBits - coefsBits - pLerpBits; // 11
|
||||
static const uint32_t pMask = ((1<<pLerpBits)-1) << pShift; // 0x7fff << 11
|
||||
|
||||
// number of zero-crossing on each side
|
||||
static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/
|
Loading…
Reference in New Issue
Block a user