SmartAudio/package/allwinner/tina_multimedia/libcedarx/android_adapter/base/awMediaDataSource.cpp

509 lines
14 KiB
C++
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : awMediaDataSource.cpp
* Description :
* History :
* Author : SW5
* Date : 2017/04/12
* Comment : first version
*
*/
#if (CONF_ANDROID_MAJOR_VER >= 6)
//#define LOG_NDEBUG 0
#define LOG_TAG "awMediaDataSource"
#include "cdx_log.h"
#include <CdxAtomic.h>
#include "awMediaDataSource.h"
#define SAVE_FILE (0)
#if SAVE_FILE
FILE *file = NULL;
#endif
using namespace android;
struct awMediaDataSource : public RefBase
{
awMediaDataSource(const sp<DataSource> &source);
virtual ssize_t readAt(char* buffer, size_t size);
virtual off64_t getSize();
virtual off64_t getOffset();
virtual ssize_t setOffset(off64_t offset);
virtual void disconnect();
protected:
virtual ~awMediaDataSource();
private:
sp<DataSource> mSource;
Mutex mLock;
off64_t mOffset;
off64_t mSourceSize;
DISALLOW_EVIL_CONSTRUCTORS(awMediaDataSource);
};
awMediaDataSource::awMediaDataSource(const sp<DataSource> &source)
: mSource(source),
mOffset(0),
mSourceSize(0)
{
CDX_LOGV("awMediaDataSource Constructor");
}
awMediaDataSource::~awMediaDataSource() {
CDX_LOGV("awMediaDataSource Constructor ~De");
}
ssize_t awMediaDataSource::readAt(char* buffer, size_t size) {
CDX_LOGV("awMediaDataSource readAt, size: %zu", size);
ssize_t err = mSource->readAt(mOffset, buffer, size);
if (err < (ssize_t)size) {
CDX_LOGE("readAt failed, err: %s", strerror(errno));
return -1;
}
mOffset += err;
return err;
}
off64_t awMediaDataSource::getSize() {
CDX_LOGV("awMediaDataSource getSize");
off64_t sourceSize;
status_t ret = mSource->getSize(&sourceSize);
if (ret != 0) {
CDX_LOGE("get size fail,unknown data source size, ret : %d sourceSize: %lld",
(int)ret, sourceSize);
mSourceSize = 0;
return 0;
}
CDX_LOGV("sourceSize: %lld", sourceSize);
mSourceSize = (sourceSize > 0 ? sourceSize:0);
return mSourceSize;
}
off64_t awMediaDataSource::getOffset() {
CDX_LOGV("awMediaDataSource getOffset, mOffset: %lld", mOffset);
return mOffset;
}
ssize_t awMediaDataSource::setOffset(off64_t offset) {
CDX_LOGV("awMediaDataSource setOffset, offset: %lld", offset);
if(mSourceSize && (offset > mSourceSize)) {
CDX_LOGE("invalid argument");
return -1;
}
mOffset = offset;
CDX_LOGV("setOffset: mOffset: %lld", mOffset);
return 0;
}
void awMediaDataSource::disconnect() {
CDX_LOGV("awMediaDataSource disconnect");
if(mSource != NULL)
mSource->close();
else
CDX_LOGW("mSource is NULL");
}
////////////////////////////////////////////////////////////////////////
#define ProbeDataLen (2*1024)
enum CdxStreamStatus
{
DATA_SOURCE_STREAM_IDLE,
DATA_SOURCE_STREAM_CONNECTING,
DATA_SOURCE_STREAM_SEEKING,
DATA_SOURCE_STREAM_READING,
};
typedef struct MediaDataSource MediaDataSource;
struct MediaDataSource
{
CdxStreamT base;
cdx_uint32 attribute;
enum CdxStreamStatus status;
cdx_int32 ioState;
pthread_mutex_t lock;
pthread_cond_t cond;
cdx_int32 forceStop;
CdxStreamProbeDataT probeData;
off64_t sourceSize;
sp<awMediaDataSource> mAwMediaDataSource;
};
static cdx_int32 DataSourceStreamConnect(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
pthread_mutex_lock(&dataSource->lock);
cdx_int32 ret = 0;
ssize_t err;
if(dataSource->forceStop)
{
pthread_mutex_unlock(&dataSource->lock);
return -1;
}
dataSource->status = DATA_SOURCE_STREAM_CONNECTING;
pthread_mutex_unlock(&dataSource->lock);
dataSource->sourceSize = dataSource->mAwMediaDataSource->getSize();
if(dataSource->sourceSize == 0)
{
CDX_LOGE("unable to get soure size");
dataSource->attribute = CDX_STREAM_FLAG_NET;
}
err = dataSource->mAwMediaDataSource->readAt(dataSource->probeData.buf,
ProbeDataLen);
if (err < (ssize_t)ProbeDataLen) {
CDX_LOGE("readAt failed");
ret = -1;
goto __failure;
}
err = dataSource->mAwMediaDataSource->setOffset(0);
if(err != 0)
{
CDX_LOGE("setOffset failed");
ret = -1;
goto __failure;
}
dataSource->ioState = CDX_IO_STATE_OK;
pthread_mutex_lock(&dataSource->lock);
dataSource->status = DATA_SOURCE_STREAM_IDLE;
pthread_mutex_unlock(&dataSource->lock);
pthread_cond_signal(&dataSource->cond);
CDX_LOGV("connect succeed");
return ret;
__failure:
dataSource->ioState = CDX_IO_STATE_ERROR;
pthread_mutex_lock(&dataSource->lock);
dataSource->status = DATA_SOURCE_STREAM_IDLE;
pthread_mutex_unlock(&dataSource->lock);
pthread_cond_signal(&dataSource->cond);
CDX_LOGW("connect fail");
return ret;
}
static cdx_int32 DataSourceStreamGetIOState(CdxStreamT *stream)
{
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
return dataSource->ioState;
}
static CdxStreamProbeDataT *DataSourceStreamGetProbeData(CdxStreamT *stream)
{
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
return &dataSource->probeData;
}
static cdx_uint32 DataSourceStreamAttribute(CdxStreamT *stream)
{
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
return dataSource->attribute;
}
static cdx_int32 DataSourceStreamForceStop(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
pthread_mutex_lock(&dataSource->lock);
dataSource->forceStop = 1;
while(dataSource->status != DATA_SOURCE_STREAM_IDLE)
{
pthread_cond_wait(&dataSource->cond, &dataSource->lock);
}
pthread_mutex_unlock(&dataSource->lock);
CDX_LOGV("force stop end");
return 0;
}
static cdx_int32 DataSourceStreamClrForceStop(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
pthread_mutex_lock(&dataSource->lock);
dataSource->forceStop = 0;
dataSource->status = DATA_SOURCE_STREAM_IDLE;
pthread_mutex_unlock(&dataSource->lock);
return 0;
}
static cdx_int32 DataSourceStreamControl(CdxStreamT *stream, cdx_int32 cmd, void *param)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_UNUSE(param);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
switch(cmd)
{
case STREAM_CMD_SET_FORCESTOP:
return DataSourceStreamForceStop(stream);
case STREAM_CMD_CLR_FORCESTOP:
return DataSourceStreamClrForceStop(stream);
default:
CDX_LOGW("not implement cmd(%d)", cmd);
break;
}
return -1;
}
static cdx_int32 DataSourceStreamRead(CdxStreamT *stream, void *buf, cdx_uint32 len)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
pthread_mutex_lock(&dataSource->lock);
if(dataSource->forceStop)
{
pthread_mutex_unlock(&dataSource->lock);
return -1;
}
dataSource->status = DATA_SOURCE_STREAM_READING;
pthread_mutex_unlock(&dataSource->lock);
char *data = (char *)buf;
ssize_t ret = 0;
cdx_int64 pos = dataSource->mAwMediaDataSource->getOffset();
CDX_LOGV("read--pos: %lld", pos);
if(pos >= dataSource->sourceSize
&& dataSource->sourceSize != 0)
{
CDX_LOGD("eos");
pthread_mutex_lock(&dataSource->lock);
dataSource->status = DATA_SOURCE_STREAM_IDLE;
dataSource->ioState = CDX_IO_STATE_EOS;
pthread_mutex_unlock(&dataSource->lock);
pthread_cond_signal(&dataSource->cond);
return 0;
}
ret = dataSource->mAwMediaDataSource->readAt(data, len);
CDX_LOGV("len: %d", len);
//CDX_BUF_DUMP(data, len);
if(ret == (ssize_t)0)
{
dataSource->ioState = CDX_IO_STATE_EOS;
}
else if(ret < (ssize_t)0)
{
CDX_LOGE("readAt fail");
}
#if SAVE_FILE
if(ret > (ssize_t)0)
{
if (file)
{
fwrite(data, 1, ret, file);
sync();
}
else
{
CDX_LOGW("save file = NULL");
}
}
#endif
pthread_mutex_lock(&dataSource->lock);
dataSource->status = DATA_SOURCE_STREAM_IDLE;
pthread_mutex_unlock(&dataSource->lock);
pthread_cond_signal(&dataSource->cond);
return ret;
}
static cdx_int32 DataSourceStreamSeek(CdxStreamT *stream, cdx_int64 offset,
cdx_int32 whence)
{
CDX_LOGV("L: %d, func: %s, offset: %lld", __LINE__, __func__, offset);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
cdx_int64 ret = 0;
pthread_mutex_lock(&dataSource->lock);
if(dataSource->forceStop)
{
pthread_mutex_unlock(&dataSource->lock);
return -1;
}
dataSource->status = DATA_SOURCE_STREAM_SEEKING;
pthread_mutex_unlock(&dataSource->lock);
switch (whence)
{
case STREAM_SEEK_SET:
{
if(offset < 0 || offset > dataSource->sourceSize)
{
CDX_LOGE("invalid arguments, offset(%lld), size(%lld)",
offset, dataSource->sourceSize);
ret = -1;
goto _exit;
}
ret = dataSource->mAwMediaDataSource->setOffset(offset);
break;
}
case STREAM_SEEK_CUR:
{
cdx_int64 cur_pos = dataSource->mAwMediaDataSource->getOffset();
if (cur_pos + offset < 0 || cur_pos + offset > dataSource->sourceSize)
{
CDX_LOGE("invalid arguments, offset(%lld), size(%lld), curPos(%lld)",
offset, dataSource->sourceSize, cur_pos);
ret = -1;
goto _exit;
}
ret = dataSource->mAwMediaDataSource->setOffset(cur_pos + offset);
break;
}
case STREAM_SEEK_END:
{
cdx_int64 cur_pos = dataSource->mAwMediaDataSource->getOffset();
cdx_int64 absOffset = cur_pos + dataSource->sourceSize + offset;
if (absOffset < cur_pos || absOffset > cur_pos + dataSource->sourceSize)
{
CDX_LOGE("invalid arguments, offset(%lld), size(%lld)",
absOffset, cur_pos + dataSource->sourceSize);
ret = -1;
goto _exit;
}
ret = dataSource->mAwMediaDataSource->setOffset(dataSource->sourceSize - offset);
break;
}
default :
CDX_CHECK(0);
break;
}
_exit:
pthread_mutex_lock(&dataSource->lock);
dataSource->status = DATA_SOURCE_STREAM_IDLE;
pthread_mutex_unlock(&dataSource->lock);
pthread_cond_signal(&dataSource->cond);
return ret;
}
static cdx_int64 DataSourceStreamSize(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
return dataSource->sourceSize;
}
static cdx_int64 DataSourceStreamTell(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
return dataSource->mAwMediaDataSource->getOffset();
}
static cdx_bool DataSourceStreamEos(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
cdx_int64 pos = dataSource->mAwMediaDataSource->getOffset();
cdx_int64 size = dataSource->sourceSize;
return (pos == size);
}
static cdx_int32 DataSourceStreamClose(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_UNUSE(stream);
return 0;
}
CdxStreamT* MediaDataSourceOpen(const sp<DataSource> &source)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
MediaDataSource *dataSource = (MediaDataSource *)malloc(sizeof(MediaDataSource));
if(!dataSource)
{
CDX_LOGE("malloc fail!");
return NULL;
}
memset(dataSource, 0x00, sizeof(MediaDataSource));
int ret = pthread_mutex_init(&dataSource->lock, NULL);
CDX_CHECK(!ret);
ret = pthread_cond_init(&dataSource->cond, NULL);
CDX_CHECK(!ret);
dataSource->probeData.len = ProbeDataLen;
dataSource->probeData.buf = (cdx_char *)malloc(ProbeDataLen);
CDX_CHECK(dataSource->probeData.buf);
dataSource->mAwMediaDataSource = new awMediaDataSource(source);
dataSource->ioState = CDX_IO_STATE_INVALID;
dataSource->attribute = CDX_STREAM_FLAG_SEEK;
dataSource->status = DATA_SOURCE_STREAM_IDLE;
dataSource->base.ops = (struct CdxStreamOpsS *)malloc(sizeof(struct CdxStreamOpsS));
CDX_CHECK(dataSource->base.ops);
memset(dataSource->base.ops, 0, sizeof(struct CdxStreamOpsS));
dataSource->base.ops->getProbeData = DataSourceStreamGetProbeData;
dataSource->base.ops->read = DataSourceStreamRead;
dataSource->base.ops->close = DataSourceStreamClose;
dataSource->base.ops->getIOState = DataSourceStreamGetIOState;
dataSource->base.ops->attribute = DataSourceStreamAttribute;
dataSource->base.ops->control = DataSourceStreamControl;
dataSource->base.ops->connect = DataSourceStreamConnect;
dataSource->base.ops->seek = DataSourceStreamSeek;
dataSource->base.ops->eos = DataSourceStreamEos;
dataSource->base.ops->tell = DataSourceStreamTell;
dataSource->base.ops->size = DataSourceStreamSize;
#if SAVE_FILE
file = fopen("/data/camera/save.dat", "wb+");
if (!file)
{
CDX_LOGE("open file failure errno(%d)", errno);
}
#endif
return &dataSource->base;
}
cdx_int32 MediaDataSourceClose(CdxStreamT *stream)
{
CDX_LOGV("L: %d, func: %s", __LINE__, __func__);
CDX_CHECK(stream);
MediaDataSource *dataSource = (MediaDataSource *)stream;
DataSourceStreamForceStop(stream);
dataSource->mAwMediaDataSource->disconnect();
if(dataSource->probeData.buf)
free(dataSource->probeData.buf);
if(dataSource->base.ops)
free(dataSource->base.ops);
#if SAVE_FILE
if (file)
{
fclose(file);
file = NULL;
}
#endif
pthread_mutex_destroy(&dataSource->lock);
pthread_cond_destroy(&dataSource->cond);
free(dataSource);
return 0;
}
#endif