2066 lines
66 KiB
C++
2066 lines
66 KiB
C++
|
/*
|
|||
|
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
|
|||
|
* All rights reserved.
|
|||
|
*
|
|||
|
* File : awplayer.cpp
|
|||
|
* Description : mediaplayer adapter for operator
|
|||
|
* History :
|
|||
|
* Author : AL3
|
|||
|
* Date : 2015/05/05
|
|||
|
* Comment : first version
|
|||
|
*
|
|||
|
*/
|
|||
|
#define LOG_TAG "awplayer"
|
|||
|
|
|||
|
#include "cdx_log.h"
|
|||
|
#include "awplayer.h"
|
|||
|
#include "subtitleUtils.h"
|
|||
|
#include "awStreamingSource.h"
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#include <media/Metadata.h>
|
|||
|
#include <media/mediaplayer.h>
|
|||
|
#include <binder/IPCThreadState.h>
|
|||
|
#include <media/IAudioFlinger.h>
|
|||
|
#include <fcntl.h>
|
|||
|
#include <cutils/properties.h> // for property_get
|
|||
|
#include <hardware/hwcomposer.h>
|
|||
|
|
|||
|
#include <version.h>
|
|||
|
#include "xplayer.h"
|
|||
|
#include "player.h"
|
|||
|
#include "mediaInfo.h"
|
|||
|
#include "AwMessageQueue.h"
|
|||
|
#include "awLogRecorder.h"
|
|||
|
#include "AwHDCPModule.h"
|
|||
|
#include "outputCtrl.h"
|
|||
|
#include "awLogRecorder.h"
|
|||
|
#include "cdx_config.h"
|
|||
|
#include "soundControl.h"
|
|||
|
|
|||
|
//wasu livemode4 , apk set seekTo after start, we should call start after seek
|
|||
|
#define CMCC_LIVEMODE_4_BUG (1)
|
|||
|
|
|||
|
// the cmcc apk bug, change channel when buffering icon is displayed,
|
|||
|
// the buffering icon is not diappered, so we send a buffer end message in prepare/prepareAsync
|
|||
|
#define BUFFERING_ICON_BUG (1)
|
|||
|
|
|||
|
// pause then start to display, the cmcc apk call seekTo, it will flush the buffering cache(livemod)
|
|||
|
// or seek some frames in cache ( vod) , it will discontinue
|
|||
|
#define PAUSE_THEN_SEEK_BUG (1)
|
|||
|
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
//* android 4.4 use IGraphicBufferProducer instead of ISurfaceTexture in android 4.2.
|
|||
|
#include <gui/IGraphicBufferProducer.h>
|
|||
|
#include <gui/Surface.h>
|
|||
|
#endif
|
|||
|
|
|||
|
static const char *WASU_APP_NAME = "net.sunniwell.app.ott.chinamobile";
|
|||
|
static const char *CMCC_LOCAL_APP_NAME = "net.sunniwell.app.swplayer";
|
|||
|
// static const char *MANGGUO_APP_NAME = "com.starcor.hunan";
|
|||
|
|
|||
|
static int XPlayerCallbackProcess(void* pUser, int eMessageId, int ext1, void* ext2);
|
|||
|
static int GetCallingApkName(char* strApkName, int nMaxNameSize);
|
|||
|
static int SubCallbackProcess(void* pUser, int eMessageId, void* param);
|
|||
|
|
|||
|
typedef struct PlayerPriData
|
|||
|
{
|
|||
|
XPlayer* mXPlayer;
|
|||
|
XPlayerConfig_t mConfigInfo;
|
|||
|
uid_t mUID; //* no use.
|
|||
|
|
|||
|
//* surface.
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
//* android 4.4 use IGraphicBufferProducer instead of ISurfaceTexture in android 4.2.
|
|||
|
sp<IGraphicBufferProducer> mGraphicBufferProducer;
|
|||
|
#else
|
|||
|
sp<ISurfaceTexture> mSurfaceTexture;
|
|||
|
#endif
|
|||
|
sp<ANativeWindow> mNativeWindow;
|
|||
|
|
|||
|
char strApkName[128];
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 5)
|
|||
|
sp<IMediaHTTPService> mHTTPService;
|
|||
|
#endif
|
|||
|
|
|||
|
//* record the id of subtitle which is displaying
|
|||
|
//* we set the Nums to 64 .(32 may be not enough)
|
|||
|
unsigned int mSubtitleDisplayIds[64];
|
|||
|
int mSubtitleDisplayIdsUpdateIndex;
|
|||
|
|
|||
|
//* note whether the sutitle is in text or in bitmap format.
|
|||
|
int mIsSubtitleInTextFormat;
|
|||
|
|
|||
|
//* text codec format of the subtitle, used to transform subtitle text to
|
|||
|
//* utf8 when the subtitle text codec format is unknown.
|
|||
|
char mDefaultTextFormat[32];
|
|||
|
|
|||
|
//* whether enable subtitle show.
|
|||
|
int mIsSubtitleDisable;
|
|||
|
|
|||
|
//* file descriptor of .idx file of index+sub subtitle.
|
|||
|
//* we save the .idx file's fd here because application set .idx file and .sub file
|
|||
|
//* seperately, we need to wait for the .sub file's fd, see
|
|||
|
//* INVOKE_ID_ADD_EXTERNAL_SOURCE_FD command in invoke() method.
|
|||
|
int mIndexFileHasBeenSet;
|
|||
|
int mIndexFileFdOfIndexSubtitle;
|
|||
|
|
|||
|
//* save the currentSelectTrackIndex;
|
|||
|
int mCurrentSelectVidoeTrackIndex;
|
|||
|
int mCurrentSelectAudioTrackIndex;
|
|||
|
int mCurrentSelectSubTrackIndex;
|
|||
|
|
|||
|
AwLogRecorder* mLogRecorder;
|
|||
|
int mbIsDiagnose;
|
|||
|
|
|||
|
int64_t mPlayTimeMs;
|
|||
|
int64_t mBufferTimeMs;
|
|||
|
|
|||
|
int mFirstStart;
|
|||
|
|
|||
|
int mKeepLastFrame;
|
|||
|
//* for subtitle.
|
|||
|
int mIsFirstItem;
|
|||
|
}PlayerPriData;
|
|||
|
|
|||
|
|
|||
|
static int resumeMediaScanner(const char* strApkName)
|
|||
|
{
|
|||
|
CEDARX_UNUSE(strApkName);
|
|||
|
return property_set("mediasw.stopscaner", "0");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static int pauseMediaScanner(const char* strApkName)
|
|||
|
{
|
|||
|
CEDARX_UNUSE(strApkName);
|
|||
|
return property_set("mediasw.stopscaner", "1");
|
|||
|
}
|
|||
|
|
|||
|
void enableMediaBoost(MediaInfo* mi);
|
|||
|
void disableMediaBoost();
|
|||
|
|
|||
|
AwPlayer::Instance AwPlayer::instance = {0, PTHREAD_MUTEX_INITIALIZER};
|
|||
|
|
|||
|
AwPlayer::AwPlayer()
|
|||
|
{
|
|||
|
logd("AwPlayer construct.");
|
|||
|
pthread_mutex_lock(&instance.lock);
|
|||
|
instance.count++;
|
|||
|
pthread_mutex_unlock(&instance.lock);
|
|||
|
|
|||
|
mPriData = (PlayerPriData*)malloc(sizeof(PlayerPriData));
|
|||
|
memset(mPriData,0x00,sizeof(PlayerPriData));
|
|||
|
|
|||
|
mPriData->mLogRecorder = NULL;
|
|||
|
|
|||
|
mPriData->mIsSubtitleDisable = 1;
|
|||
|
mPriData->mIsFirstItem = 0;
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
//* android 4.4 use IGraphicBufferProducer instead of ISurfaceTexture in android 4.2.
|
|||
|
mPriData->mGraphicBufferProducer = NULL;
|
|||
|
#else
|
|||
|
mPriData->mSurfaceTexture = NULL;
|
|||
|
#endif
|
|||
|
mPriData->mNativeWindow = NULL;
|
|||
|
mPriData->mKeepLastFrame = 0;
|
|||
|
|
|||
|
GetCallingApkName(mPriData->strApkName, sizeof(mPriData->strApkName));
|
|||
|
|
|||
|
mPriData->mXPlayer = XPlayerCreate();
|
|||
|
if(mPriData->mXPlayer != NULL)
|
|||
|
{
|
|||
|
struct HdcpOpsS hdcpOps;
|
|||
|
hdcpOps.init = HDCP_Init;
|
|||
|
hdcpOps.deinit = HDCP_Deinit;
|
|||
|
hdcpOps.decrypt = HDCP_Decrypt;
|
|||
|
XPlayerSetHdcpOps(mPriData->mXPlayer, &hdcpOps);
|
|||
|
XPlayerSetNotifyCallback(mPriData->mXPlayer, XPlayerCallbackProcess, this);
|
|||
|
|
|||
|
SubCtrl* pSubCtrl = NULL;
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER < 6)
|
|||
|
if (!strcmp(mPriData->strApkName, CMCC_LOCAL_APP_NAME))
|
|||
|
pSubCtrl = SubNativeRenderCreate();
|
|||
|
else
|
|||
|
#endif
|
|||
|
pSubCtrl = SubtitleCreate(SubCallbackProcess, this);
|
|||
|
|
|||
|
XPlayerSetSubCtrl(mPriData->mXPlayer, pSubCtrl);
|
|||
|
|
|||
|
Deinterlace* di = DeinterlaceCreate();
|
|||
|
XPlayerSetDeinterlace(mPriData->mXPlayer, di);
|
|||
|
}
|
|||
|
mPriData->mFirstStart = 1;
|
|||
|
|
|||
|
strcpy(mPriData->mDefaultTextFormat, "GBK");
|
|||
|
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
AwPlayer::~AwPlayer()
|
|||
|
{
|
|||
|
if(mPriData->mLogRecorder)
|
|||
|
{
|
|||
|
AwLogRecorderDestroy(mPriData->mLogRecorder);
|
|||
|
mPriData->mLogRecorder = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if(mPriData->mXPlayer != NULL)
|
|||
|
XPlayerDestroy(mPriData->mXPlayer);
|
|||
|
free(mPriData);
|
|||
|
mPriData = NULL;
|
|||
|
|
|||
|
pthread_mutex_lock(&instance.lock);
|
|||
|
instance.count--;
|
|||
|
if (instance.count == 0)
|
|||
|
disableMediaBoost();
|
|||
|
pthread_mutex_unlock(&instance.lock);
|
|||
|
logd("~AwPlayer");
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::initCheck()
|
|||
|
{
|
|||
|
logv("initCheck");
|
|||
|
|
|||
|
if(mPriData->mXPlayer == NULL)
|
|||
|
{
|
|||
|
loge("initCheck() fail, XPlayer::mplayer = %p", mPriData->mXPlayer);
|
|||
|
return NO_INIT;
|
|||
|
}
|
|||
|
|
|||
|
return (status_t)XPlayerInitCheck(mPriData->mXPlayer);
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::setUID(uid_t uid)
|
|||
|
{
|
|||
|
logv("setUID(), uid = %d", uid);
|
|||
|
mPriData->mUID = uid;
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
static int cmccParseHeaders(CdxKeyedVectorT **header,
|
|||
|
const KeyedVector<String8, String8>* pHeaders)
|
|||
|
{
|
|||
|
int nHeaderSize;
|
|||
|
int i;
|
|||
|
|
|||
|
if (pHeaders == NULL)
|
|||
|
return 0;
|
|||
|
|
|||
|
//*remove "x-hide-urls-from-log" ?
|
|||
|
|
|||
|
nHeaderSize = pHeaders->size();
|
|||
|
if (nHeaderSize <= 0)
|
|||
|
return -1;
|
|||
|
|
|||
|
*header = CdxKeyedVectorCreate(nHeaderSize);
|
|||
|
if (*header == NULL)
|
|||
|
{
|
|||
|
logw("CdxKeyedVectorCreate() failed");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
String8 key;
|
|||
|
String8 value;
|
|||
|
for (i = 0; i < nHeaderSize; i++)
|
|||
|
{
|
|||
|
key = pHeaders->keyAt(i);
|
|||
|
value = pHeaders->valueAt(i);
|
|||
|
if (CdxKeyedVectorAdd(*header, key.string(), value.string()) != 0)
|
|||
|
{
|
|||
|
CdxKeyedVectorDestroy(*header);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 5)
|
|||
|
status_t AwPlayer::setDataSource(const sp<IMediaHTTPService> &httpService,
|
|||
|
const char* pUrl,
|
|||
|
const KeyedVector<String8,
|
|||
|
String8>* pHeaders)
|
|||
|
#else
|
|||
|
status_t AwPlayer::setDataSource(const char* pUrl,
|
|||
|
const KeyedVector<String8, String8>* pHeaders)
|
|||
|
#endif
|
|||
|
{
|
|||
|
logd("setDataSource(url), url='%s'", pUrl);
|
|||
|
|
|||
|
void* pHttpService = NULL;
|
|||
|
CdxKeyedVectorT* header = NULL;
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 5)
|
|||
|
pHttpService = (void*)httpService.get();
|
|||
|
#endif
|
|||
|
|
|||
|
int ret = cmccParseHeaders(&header, pHeaders);
|
|||
|
if (ret < 0)
|
|||
|
{
|
|||
|
loge("parse Headers failed.");
|
|||
|
return NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
int livemode;
|
|||
|
if(strstr(pUrl, "livemode=1"))
|
|||
|
{
|
|||
|
livemode = 1;
|
|||
|
}
|
|||
|
else if(strstr(pUrl, "livemode=2"))
|
|||
|
{
|
|||
|
livemode = 2;
|
|||
|
}
|
|||
|
else if(strstr(pUrl, "livemode=4"))
|
|||
|
{
|
|||
|
livemode = 4;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
livemode = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (strstr(pUrl, "diagnose=deep"))
|
|||
|
{
|
|||
|
logd("In cmcc deep diagnose");
|
|||
|
mPriData->mbIsDiagnose = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mPriData->mbIsDiagnose = 0;
|
|||
|
}
|
|||
|
|
|||
|
mPriData->mConfigInfo.livemode = livemode;
|
|||
|
if (!strcmp(mPriData->strApkName, WASU_APP_NAME))
|
|||
|
mPriData->mConfigInfo.appType = APP_CMCC_WASU;
|
|||
|
else
|
|||
|
mPriData->mConfigInfo.appType = APP_DEFAULT;
|
|||
|
|
|||
|
mPriData->mLogRecorder = NULL;
|
|||
|
#if defined(CONF_CMCC)
|
|||
|
mPriData->mLogRecorder = AwLogRecorderCreate();
|
|||
|
#endif
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
snprintf(cmccLog, sizeof(cmccLog), "[info][%s %s %d]setDataSource, url: %s",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, pUrl);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
|
|||
|
snprintf(cmccLog, sizeof(cmccLog), "[info][%s %s %d]create a new player",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
XPlayerConfig(mPriData->mXPlayer, &mPriData->mConfigInfo);
|
|||
|
XPlayerSetDataSourceUrl(mPriData->mXPlayer, pUrl, pHttpService, header);
|
|||
|
|
|||
|
CdxKeyedVectorDestroy(header);
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
//* Warning: The filedescriptor passed into this method will only be valid until
|
|||
|
//* the method returns, if you want to keep it, dup it!
|
|||
|
status_t AwPlayer::setDataSource(int fd, int64_t offset, int64_t length)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
|
|||
|
if (!strcmp(mPriData->strApkName, CMCC_LOCAL_APP_NAME))
|
|||
|
mPriData->mConfigInfo.appType = APP_CMCC_LOCAL;
|
|||
|
else
|
|||
|
mPriData->mConfigInfo.appType = APP_DEFAULT;
|
|||
|
XPlayerConfig(mPriData->mXPlayer, &mPriData->mConfigInfo);
|
|||
|
|
|||
|
ret = XPlayerSetDataSourceFd(mPriData->mXPlayer, fd, offset, length);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::setDataSource(const sp<IStreamSource> &source)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
logd("setDataSource(IStreamSource)");
|
|||
|
|
|||
|
unsigned int numBuffer, bufferSize;
|
|||
|
const char *suffix = "";
|
|||
|
if(!strcmp(mPriData->strApkName, "com.hpplay.happyplay.aw"))
|
|||
|
{
|
|||
|
numBuffer = 32;
|
|||
|
bufferSize = 32*1024;
|
|||
|
suffix = ".awts";
|
|||
|
}
|
|||
|
else if(!strcmp(mPriData->strApkName, "com.softwinner.miracastReceiver"))
|
|||
|
{
|
|||
|
numBuffer = 1024;
|
|||
|
bufferSize = 188*8;
|
|||
|
suffix = ".ts";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CDX_LOGW("this type is unknown.");
|
|||
|
numBuffer = 16;
|
|||
|
bufferSize = 4*1024;
|
|||
|
}
|
|||
|
CdxStreamT *stream = StreamingSourceOpen(source, numBuffer, bufferSize);
|
|||
|
if(stream == NULL)
|
|||
|
{
|
|||
|
loge("StreamingSourceOpen fail!");
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
char str[128];
|
|||
|
sprintf(str, "customer://%p%s",stream, suffix);
|
|||
|
//* send a set data source message.
|
|||
|
|
|||
|
mPriData->mConfigInfo.appType = APP_STREAMING;
|
|||
|
XPlayerConfig(mPriData->mXPlayer, &mPriData->mConfigInfo);
|
|||
|
|
|||
|
ret = XPlayerSetDataSourceStream(mPriData->mXPlayer, str);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
//* android 4.4 use IGraphicBufferProducer instead of ISurfaceTexture in android 4.2.
|
|||
|
status_t AwPlayer::setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer)
|
|||
|
#else
|
|||
|
status_t AwPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture)
|
|||
|
#endif
|
|||
|
{
|
|||
|
int ret;
|
|||
|
|
|||
|
sp<ANativeWindow> anw;
|
|||
|
|
|||
|
logd("process message AWPLAYER_COMMAND_SET_SURFACE.");
|
|||
|
|
|||
|
//* set native window before delete the old one.
|
|||
|
//* because the player's render thread may use the old surface
|
|||
|
//* before it receive the new surface.
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
if(bufferProducer.get() != NULL)
|
|||
|
anw = new Surface(bufferProducer);
|
|||
|
#else
|
|||
|
if(surfaceTexture.get() != NULL)
|
|||
|
anw = new SurfaceTextureClient(surfaceTexture);
|
|||
|
#endif
|
|||
|
else
|
|||
|
anw = NULL;
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]setVideoSurfaceTexture", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
LayerCtrl* lc;
|
|||
|
lc = LayerCreate(anw.get());
|
|||
|
ret = XPlayerSetVideoSurfaceTexture(mPriData->mXPlayer, lc);
|
|||
|
|
|||
|
//* save the new surface.
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
mPriData->mGraphicBufferProducer = bufferProducer;
|
|||
|
#else
|
|||
|
mPriData->mSurfaceTexture = surfaceTexture;
|
|||
|
#endif
|
|||
|
|
|||
|
if(mPriData->mNativeWindow != NULL)
|
|||
|
native_window_api_disconnect(mPriData->mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
|
|||
|
|
|||
|
mPriData->mNativeWindow = anw;
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
void AwPlayer::setAudioSink(const sp<AudioSink> &audioSink)
|
|||
|
{
|
|||
|
logv("setAudioSink");
|
|||
|
|
|||
|
SoundCtrl* sc = SoundDeviceCreate(audioSink.get());
|
|||
|
//SoundCtrl* sc = DefaultSoundDeviceCreate();
|
|||
|
XPlayerSetAudioSink(mPriData->mXPlayer, sc);
|
|||
|
|
|||
|
//* super class MediaPlayerInterface has mAudioSink.
|
|||
|
MediaPlayerInterface::setAudioSink(audioSink);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER > 5)
|
|||
|
status_t AwPlayer::setPlaybackSettings(const AudioPlaybackRate &rate)
|
|||
|
{
|
|||
|
XAudioPlaybackRate xrate;
|
|||
|
xrate.mSpeed = rate.mSpeed;
|
|||
|
xrate.mPitch= rate.mPitch;
|
|||
|
xrate.mStretchMode= (XAudioTimestretchStretchMode)rate.mStretchMode;
|
|||
|
xrate.mFallbackMode= (XAudioTimestretchFallbackMode)rate.mFallbackMode;
|
|||
|
int ret=XPlayerSetPlaybackSettings(mPriData->mXPlayer,&xrate);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::getPlaybackSettings(AudioPlaybackRate *rate)
|
|||
|
{
|
|||
|
XAudioPlaybackRate xrate;
|
|||
|
XPlayerGetPlaybackSettings(mPriData->mXPlayer,&xrate);
|
|||
|
rate->mSpeed = xrate.mSpeed;
|
|||
|
rate->mPitch = xrate.mPitch;
|
|||
|
rate->mStretchMode = (AudioTimestretchStretchMode)xrate.mStretchMode;
|
|||
|
rate->mFallbackMode = (AudioTimestretchFallbackMode)xrate.mFallbackMode;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
status_t AwPlayer::prepareAsync()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
|
|||
|
logd("prepareAsync");
|
|||
|
|
|||
|
char prop_value[512];
|
|||
|
int displayRatio = 1;
|
|||
|
//* set scaling mode by default setting.
|
|||
|
property_get("epg.default_screen_ratio", prop_value, "1");
|
|||
|
if(atoi(prop_value) == 0)
|
|||
|
{
|
|||
|
logd("++++++++ IPTV_PLAYER_CONTENTMODE_LETTERBOX");
|
|||
|
displayRatio = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
logd( "+++++++ IPTV_PLAYER_CONTENTMODE_FULL");
|
|||
|
displayRatio = 1;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONF_PRODUCT_STB)
|
|||
|
if(mPriData->mNativeWindow != NULL)
|
|||
|
{
|
|||
|
mPriData->mNativeWindow.get()->perform(mPriData->mNativeWindow.get(),
|
|||
|
NATIVE_WINDOW_SETPARAMETER,
|
|||
|
DISPLAY_CMD_SETSCREENRADIO,
|
|||
|
displayRatio);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
struct timeval tv;
|
|||
|
int64_t startTimeMs = 0;
|
|||
|
int64_t endTimeMs;
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]prepareAysnc start", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
startTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
}
|
|||
|
|
|||
|
ret = XPlayerPrepareAsync(mPriData->mXPlayer);
|
|||
|
|
|||
|
if(0 == ret && mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
endTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]Playback is ready, spend time: %lldms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, (long long int)(endTimeMs - startTimeMs));
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::prepare()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
|
|||
|
logd("prepare");
|
|||
|
char prop_value[512];
|
|||
|
int displayRatio = 1;
|
|||
|
//* set scaling mode by default setting.
|
|||
|
property_get("epg.default_screen_ratio", prop_value, "1");
|
|||
|
if(atoi(prop_value) == 0)
|
|||
|
{
|
|||
|
logd("++++++++ IPTV_PLAYER_CONTENTMODE_LETTERBOX");
|
|||
|
displayRatio = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
logd( "+++++++ IPTV_PLAYER_CONTENTMODE_FULL");
|
|||
|
displayRatio = 1;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONF_PRODUCT_STB)
|
|||
|
if(mPriData->mNativeWindow != NULL)
|
|||
|
{
|
|||
|
mPriData->mNativeWindow.get()->perform(mPriData->mNativeWindow.get(),
|
|||
|
NATIVE_WINDOW_SETPARAMETER,
|
|||
|
DISPLAY_CMD_SETSCREENRADIO,
|
|||
|
displayRatio);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
ret = XPlayerPrepare(mPriData->mXPlayer);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::start()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
MediaInfo* mi;
|
|||
|
|
|||
|
pauseMediaScanner(mPriData->strApkName);
|
|||
|
|
|||
|
mi = XPlayerGetMediaInfo(mPriData->mXPlayer);
|
|||
|
enableMediaBoost(mi);
|
|||
|
|
|||
|
mPriData->mCurrentSelectVidoeTrackIndex = 0;
|
|||
|
mPriData->mCurrentSelectAudioTrackIndex = mi->nVideoStreamNum;
|
|||
|
mPriData->mCurrentSelectSubTrackIndex = mi->nVideoStreamNum + mi->nAudioStreamNum;
|
|||
|
|
|||
|
// for livemode 4, cmcc apk invoke start before seekTo,
|
|||
|
// it will get a frame between start and seekTo,
|
|||
|
#if CMCC_LIVEMODE_4_BUG
|
|||
|
if(mPriData->mConfigInfo.livemode == 4 && mPriData->mFirstStart &&
|
|||
|
mPriData->mConfigInfo.appType == APP_CMCC_WASU)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
ret = XPlayerStart(mPriData->mXPlayer);
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]start", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
struct timeval tv;
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
mPriData->mPlayTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
}
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::stop()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]stop", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logd("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]destory this player", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
ret = XPlayerStop(mPriData->mXPlayer);
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]Playback end", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::pause()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
logd(" pause ");
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]pause", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
ret = XPlayerPause(mPriData->mXPlayer);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::seekTo(int nSeekTimeMs)
|
|||
|
{
|
|||
|
logd("==== seekTo");
|
|||
|
int ret;
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]seekTo, totime: %dms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, nSeekTimeMs);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
#if CMCC_LIVEMODE_4_BUG
|
|||
|
//for livemode4 , apk set seekTo after start, we should call start after seek
|
|||
|
if(mPriData->mConfigInfo.livemode == 4 && mPriData->mFirstStart &&
|
|||
|
mPriData->mConfigInfo.appType == APP_CMCC_WASU)
|
|||
|
{
|
|||
|
int status;
|
|||
|
mPriData->mFirstStart = 0;
|
|||
|
status = XPlayerSeekTo(mPriData->mXPlayer, nSeekTimeMs);
|
|||
|
XPlayerStart(mPriData->mXPlayer);
|
|||
|
return status;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/* 用户seek到约最后一秒,我们认为用户真正的意图是seek到最后,相关的bug有三个:
|
|||
|
*
|
|||
|
* 1. 某些parser内部的duration单位是微妙,比如60000123 us,上报给应用的
|
|||
|
* duration是毫秒,比如60000 ms,在“舍入”或“只舍不入”的影响下,应用始终无法
|
|||
|
* seek到最后;由于关键帧位置的影响,又退回前面。
|
|||
|
*
|
|||
|
* 2. yunos上的应用在seek到最后时,把duration - 1000 ms作为seekto的位置。在
|
|||
|
* HLS不开启切片内seek时,会seek到duration - 10 * 1000 ms的位置,此现象被当
|
|||
|
* 成bug报出来
|
|||
|
*
|
|||
|
* 3. cmcc本地播放器舍去了duration里小于1秒的零头,导致无法seek到最后。测试
|
|||
|
* 关键帧间隔较大的mp4视频,会反复退回到离末尾较远的位置,会被当成seek失败
|
|||
|
*/
|
|||
|
if (mPriData->mConfigInfo.livemode == 0)
|
|||
|
{
|
|||
|
int dura = 0;
|
|||
|
ret = XPlayerGetDuration(mPriData->mXPlayer, &dura);
|
|||
|
int n = nSeekTimeMs + 1000;
|
|||
|
if (ret == 0 && dura > 0 && n >= dura)
|
|||
|
{
|
|||
|
logd("change seek position from %d to %d", nSeekTimeMs, n);
|
|||
|
nSeekTimeMs = n;
|
|||
|
}
|
|||
|
}
|
|||
|
ret = XPlayerSeekTo(mPriData->mXPlayer, nSeekTimeMs);
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]seek complete", LOG_TAG, __FUNCTION__, __LINE__);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::reset()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
logd("... reset");
|
|||
|
resumeMediaScanner(mPriData->strApkName);
|
|||
|
|
|||
|
ret = XPlayerReset(mPriData->mXPlayer);
|
|||
|
|
|||
|
//* clear suface.
|
|||
|
if(mPriData->mKeepLastFrame == 0)
|
|||
|
{
|
|||
|
if(mPriData->mNativeWindow != NULL)
|
|||
|
native_window_api_disconnect(mPriData->mNativeWindow.get(),
|
|||
|
NATIVE_WINDOW_API_MEDIA);
|
|||
|
mPriData->mNativeWindow.clear();
|
|||
|
#if (!((CONF_ANDROID_MAJOR_VER == 4)&&(CONF_ANDROID_SUB_VER == 2)))
|
|||
|
mPriData->mGraphicBufferProducer.clear();
|
|||
|
#else
|
|||
|
mPriData->mSurfaceTexture.clear();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//* clear audio sink.
|
|||
|
mAudioSink.clear();
|
|||
|
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::setSpeed(int nSpeed)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
ret = XPlayerSetSpeed(mPriData->mXPlayer, nSpeed);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
bool AwPlayer::isPlaying()
|
|||
|
{
|
|||
|
int ret;
|
|||
|
ret = XPlayerIsPlaying(mPriData->mXPlayer);
|
|||
|
|
|||
|
return (ret == 1)? true : false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::getCurrentPosition(int* msec)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
ret = XPlayerGetCurrentPosition(mPriData->mXPlayer, msec);
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]current playtime: %dms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, *msec);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::getDuration(int *msec)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
ret = XPlayerGetDuration(mPriData->mXPlayer, msec);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::setLooping(int loop)
|
|||
|
{
|
|||
|
int ret;
|
|||
|
ret = XPlayerSetLooping(mPriData->mXPlayer, loop);
|
|||
|
|
|||
|
return (status_t)ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
player_type AwPlayer::playerType()
|
|||
|
{
|
|||
|
logv("playerType");
|
|||
|
return AW_PLAYER;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::invoke(const Parcel &request, Parcel *reply)
|
|||
|
{
|
|||
|
int nMethodId;
|
|||
|
int ret;
|
|||
|
MediaInfo* mi;
|
|||
|
|
|||
|
logv("invoke()");
|
|||
|
|
|||
|
ret = request.readInt32(&nMethodId);
|
|||
|
if(ret != OK)
|
|||
|
return ret;
|
|||
|
|
|||
|
mi = XPlayerGetMediaInfo(mPriData->mXPlayer);
|
|||
|
switch(nMethodId)
|
|||
|
{
|
|||
|
case INVOKE_ID_GET_TRACK_INFO: //* get media stream counts.
|
|||
|
{
|
|||
|
logv("invode::INVOKE_ID_GET_TRACK_INFO");
|
|||
|
|
|||
|
if(mi == NULL)
|
|||
|
{
|
|||
|
return NO_INIT;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
int i;
|
|||
|
int nTrackCount;
|
|||
|
const char* lang;
|
|||
|
|
|||
|
nTrackCount = mi->nVideoStreamNum + mi->nAudioStreamNum +
|
|||
|
mi->nSubtitleStreamNum;
|
|||
|
#if AWPLAYER_CONFIG_DISABLE_VIDEO
|
|||
|
nTrackCount -= mi->nVideoStreamNum;
|
|||
|
#endif
|
|||
|
#if AWPLAYER_CONFIG_DISABLE_AUDIO
|
|||
|
nTrackCount -= mi->nAudioStreamNum;
|
|||
|
#endif
|
|||
|
#if AWPLAYER_CONFIG_DISABLE_SUBTITLE
|
|||
|
nTrackCount -= mi->nSubtitleStreamNum;
|
|||
|
#endif
|
|||
|
reply->writeInt32(nTrackCount);
|
|||
|
|
|||
|
#if !AWPLAYER_CONFIG_DISABLE_VIDEO
|
|||
|
for(i=0; i<mi->nVideoStreamNum; i++)
|
|||
|
{
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
reply->writeInt32(4);
|
|||
|
#else
|
|||
|
reply->writeInt32(2);
|
|||
|
#endif
|
|||
|
reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 6)
|
|||
|
reply->writeString16(String16("video/"));
|
|||
|
#endif
|
|||
|
lang = " ";
|
|||
|
reply->writeString16(String16(lang));
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
reply->writeInt32(mi->pVideoStreamInfo[i].bIs3DStream);
|
|||
|
//Please refer to the "enum EVIDEOCODECFORMAT" in "vdecoder.h"
|
|||
|
reply->writeInt32(mi->pVideoStreamInfo[i].eCodecFormat);
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
#if !AWPLAYER_CONFIG_DISABLE_AUDIO
|
|||
|
for(i=0; i<mi->nAudioStreamNum; i++)
|
|||
|
{
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
reply->writeInt32(6);
|
|||
|
#else
|
|||
|
reply->writeInt32(2);
|
|||
|
#endif
|
|||
|
reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 6)
|
|||
|
reply->writeString16(String16("audio/"));
|
|||
|
#endif
|
|||
|
|
|||
|
if(mi->pAudioStreamInfo[i].strLang[0] != 0)
|
|||
|
{
|
|||
|
lang = (const char*)mi->pAudioStreamInfo[i].strLang;
|
|||
|
reply->writeString16(String16(lang));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
lang = "";
|
|||
|
reply->writeString16(String16(lang));
|
|||
|
}
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
reply->writeInt32(mi->pAudioStreamInfo[i].nChannelNum);
|
|||
|
reply->writeInt32(mi->pAudioStreamInfo[i].nSampleRate);
|
|||
|
reply->writeInt32(mi->pAudioStreamInfo[i].nAvgBitrate);
|
|||
|
//Please refer to the "enum EAUDIOCODECFORMAT" in "adecoder.h"
|
|||
|
reply->writeInt32(mi->pAudioStreamInfo[i].eCodecFormat);
|
|||
|
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if !AWPLAYER_CONFIG_DISABLE_SUBTITLE
|
|||
|
for(i=0; i<mi->nSubtitleStreamNum; i++)
|
|||
|
{
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
reply->writeInt32(4);
|
|||
|
#else
|
|||
|
reply->writeInt32(2);
|
|||
|
#endif
|
|||
|
reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 6)
|
|||
|
reply->writeString16(String16("text/3gpp-tt"));
|
|||
|
#endif
|
|||
|
if (mi->pSubtitleStreamInfo[i].strLang[0] != 0)
|
|||
|
{
|
|||
|
lang = (const char*)mi->pSubtitleStreamInfo[i].strLang;
|
|||
|
reply->writeString16(String16(lang));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
lang = "";
|
|||
|
reply->writeString16(String16(lang));
|
|||
|
}
|
|||
|
#if defined(CONF_DETAIL_TRACK_INFO)
|
|||
|
//Please refer to the "ESubtitleCodec" in "sdecoder.h"
|
|||
|
reply->writeInt32(mi->pSubtitleStreamInfo[i].eCodecFormat);
|
|||
|
reply->writeInt32(mi->pSubtitleStreamInfo[i].bExternal);
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
case INVOKE_ID_ADD_EXTERNAL_SOURCE:
|
|||
|
case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
|
|||
|
{
|
|||
|
logd("=== INVOKE_ID_ADD_EXTERNAL_SOURCE");
|
|||
|
int fd;
|
|||
|
int64_t nOffset;
|
|||
|
int64_t nLength;
|
|||
|
int fdSub;
|
|||
|
|
|||
|
if(nMethodId == INVOKE_ID_ADD_EXTERNAL_SOURCE)
|
|||
|
{
|
|||
|
//* string values written in Parcel are UTF-16 values.
|
|||
|
String8 uri(request.readString16());
|
|||
|
String8 mimeType(request.readString16());
|
|||
|
|
|||
|
//* if mimeType == "application/sub" and mIndexFileHasBeenSet == 0,
|
|||
|
//* the .sub file is a common .sub subtitle, not index+sub subtitle.
|
|||
|
|
|||
|
if(strcmp((char*)mimeType.string(), "application/sub") == 0 &&
|
|||
|
mPriData->mIndexFileHasBeenSet == 1)
|
|||
|
{
|
|||
|
//* the .sub file of index+sub subtitle.
|
|||
|
//* no need to use the .sub file url, because subtitle decoder will
|
|||
|
//* find the .sub file by itself by using the .idx file's url.
|
|||
|
//* mimetype "application/sub" is defined in
|
|||
|
//* "android/base/media/java/android/media/MediaPlayer.java".
|
|||
|
//* clear the flag for adding more subtitle.
|
|||
|
mPriData->mIndexFileHasBeenSet = 0;
|
|||
|
return OK;
|
|||
|
}
|
|||
|
else if(strcmp((char*)mimeType.string(), "application/idx+sub") == 0)
|
|||
|
{
|
|||
|
//* set this flag to process the .sub file passed in at next call.
|
|||
|
mPriData->mIndexFileHasBeenSet = 1;
|
|||
|
}
|
|||
|
|
|||
|
//* probe subtitle info
|
|||
|
XPlayerSetExternalSubUrl(mPriData->mXPlayer, uri.string());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
fd = request.readFileDescriptor();
|
|||
|
nOffset = request.readInt64();
|
|||
|
nLength = request.readInt64();
|
|||
|
fdSub = -1;
|
|||
|
String8 mimeType(request.readString16());
|
|||
|
|
|||
|
//* if mimeType == "application/sub" and mIndexFileHasBeenSet == 0,
|
|||
|
//* the .sub file is a common .sub subtitle, not index+sub subtitle.
|
|||
|
|
|||
|
if(strcmp((char*)mimeType.string(), "application/idx-sub") == 0)
|
|||
|
{
|
|||
|
//* the .idx file of index+sub subtitle.
|
|||
|
mPriData->mIndexFileFdOfIndexSubtitle = dup(fd);
|
|||
|
mPriData->mIndexFileHasBeenSet = 1;
|
|||
|
return OK;
|
|||
|
}
|
|||
|
else if(strcmp((char*)mimeType.string(), "application/sub") == 0 &&
|
|||
|
mPriData->mIndexFileHasBeenSet == 1)
|
|||
|
{
|
|||
|
//* the .sub file of index+sub subtitle.
|
|||
|
//* for index+sub subtitle, PlayerProbeSubtitleStreamInfoFd() method need
|
|||
|
//* the .idx file's descriptor for probe.
|
|||
|
fdSub = fd; //* save the .sub file's descriptor to fdSub.
|
|||
|
//* set the .idx file's descriptor to fd.
|
|||
|
fd = mPriData->mIndexFileFdOfIndexSubtitle;
|
|||
|
mPriData->mIndexFileFdOfIndexSubtitle = -1;
|
|||
|
mPriData->mIndexFileHasBeenSet = 0;//* clear the flag for adding more subtitle.
|
|||
|
}
|
|||
|
|
|||
|
//* probe subtitle info
|
|||
|
XPlayerSetExternalSubFd(mPriData->mXPlayer, fd,nOffset,nLength, fdSub);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case INVOKE_ID_SELECT_TRACK:
|
|||
|
case INVOKE_ID_UNSELECT_TRACK:
|
|||
|
{
|
|||
|
int nStreamIndex;
|
|||
|
int nTrackCount;
|
|||
|
|
|||
|
nStreamIndex = request.readInt32();
|
|||
|
logd("invode::INVOKE_ID_SELECT_TRACK, stream index = %d", nStreamIndex);
|
|||
|
|
|||
|
if(mi == NULL)
|
|||
|
{
|
|||
|
loge("can not switch audio or subtitle, there is no media stream.");
|
|||
|
return NO_INIT;
|
|||
|
}
|
|||
|
|
|||
|
nTrackCount = mi->nVideoStreamNum + mi->nAudioStreamNum +
|
|||
|
mi->nSubtitleStreamNum;
|
|||
|
if(nTrackCount == 0)
|
|||
|
{
|
|||
|
loge("can not switch audio or subtitle, there is no media stream.");
|
|||
|
return NO_INIT;
|
|||
|
}
|
|||
|
|
|||
|
if(nStreamIndex >= mi->nVideoStreamNum &&
|
|||
|
nStreamIndex < (mi->nVideoStreamNum + mi->nAudioStreamNum))
|
|||
|
{
|
|||
|
if(nMethodId == INVOKE_ID_SELECT_TRACK)
|
|||
|
{
|
|||
|
//* switch audio.
|
|||
|
mPriData->mCurrentSelectAudioTrackIndex = nStreamIndex;
|
|||
|
nStreamIndex -= mi->nVideoStreamNum;
|
|||
|
if(XPlayerSwitchAudio(mPriData->mXPlayer, nStreamIndex) != 0)
|
|||
|
{
|
|||
|
loge("can not switch audio, call PlayerSwitchAudio() return fail.");
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mPriData->mCurrentSelectAudioTrackIndex = -1;
|
|||
|
loge("Deselect an audio track (%d) is not supported", nStreamIndex);
|
|||
|
return INVALID_OPERATION;
|
|||
|
}
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
else if(nStreamIndex >= (mi->nVideoStreamNum + mi->nAudioStreamNum) &&
|
|||
|
nStreamIndex < nTrackCount)
|
|||
|
{
|
|||
|
if(nMethodId == INVOKE_ID_SELECT_TRACK)
|
|||
|
{
|
|||
|
logv("==== INVOKE_ID_SELECT_TRACK, nStreamIndex: %d", nStreamIndex);
|
|||
|
//* enable subtitle.
|
|||
|
mPriData->mIsSubtitleDisable = 0;
|
|||
|
mPriData->mCurrentSelectSubTrackIndex = nStreamIndex;
|
|||
|
|
|||
|
//* switch subtitle.
|
|||
|
nStreamIndex -= (mi->nVideoStreamNum + mi->nAudioStreamNum);
|
|||
|
if(XPlayerSwitchSubtitle(mPriData->mXPlayer, nStreamIndex) != 0)
|
|||
|
{
|
|||
|
loge("can not switch subtitle, call PlayerSwitchSubtitle() return fail.");
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
mPriData->mIsFirstItem = 1;
|
|||
|
logv("mIsFirstItem: %d", mPriData->mIsFirstItem);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
logv("==== INVOKE_ID_DESELECT_TRACK, nStreamIndex: %d", nStreamIndex);
|
|||
|
if(mPriData->mCurrentSelectSubTrackIndex != nStreamIndex)
|
|||
|
{
|
|||
|
logw("the unselectTrack is not right: %d, %d",
|
|||
|
mPriData->mCurrentSelectSubTrackIndex,nStreamIndex);
|
|||
|
return INVALID_OPERATION;
|
|||
|
}
|
|||
|
|
|||
|
mPriData->mIsSubtitleDisable = 1; //* disable subtitle show.
|
|||
|
sendEvent(MEDIA_TIMED_TEXT);//* clear all the displaying subtitle
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
mPriData->mCurrentSelectSubTrackIndex = -1;
|
|||
|
}
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
if(nMethodId == INVOKE_ID_SELECT_TRACK)
|
|||
|
{
|
|||
|
loge("can not switch audio or subtitle to track %d, \
|
|||
|
stream index exceed.(%d stream in total).",
|
|||
|
nStreamIndex, nTrackCount);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
loge("can not unselect track %d, stream index exceed.(%d stream in total).",
|
|||
|
nStreamIndex, nTrackCount);
|
|||
|
}
|
|||
|
return BAD_INDEX;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case INVOKE_ID_SET_VIDEO_SCALING_MODE:
|
|||
|
{
|
|||
|
int nStreamIndex;
|
|||
|
|
|||
|
nStreamIndex = request.readInt32();
|
|||
|
logv("invode::INVOKE_ID_SET_VIDEO_SCALING_MODE");
|
|||
|
//* TODO.
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONF_PRODUCT_STB)
|
|||
|
case INVOKE_ID_SET_3D_MODE:
|
|||
|
{
|
|||
|
logd(" donot set 3d mode");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case INVOKE_ID_GET_3D_MODE:
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if (CONF_ANDROID_MAJOR_VER >= 5)
|
|||
|
case INVOKE_ID_GET_SELECTED_TRACK:
|
|||
|
{
|
|||
|
int trackType = request.readInt32();
|
|||
|
logd("==== invoke: INVOKE_ID_GET_SELECTED_TRACK, trackType(%d)", trackType);
|
|||
|
logd("=== mCurrentSelectSubTrackIndex: %d", mPriData->mCurrentSelectSubTrackIndex);
|
|||
|
if(trackType == MEDIA_TRACK_TYPE_VIDEO)
|
|||
|
reply->writeInt32(mPriData->mCurrentSelectVidoeTrackIndex);
|
|||
|
else if(trackType == MEDIA_TRACK_TYPE_AUDIO)
|
|||
|
reply->writeInt32(mPriData->mCurrentSelectAudioTrackIndex);
|
|||
|
else if(trackType == MEDIA_TRACK_TYPE_TIMEDTEXT ||
|
|||
|
trackType == MEDIA_TRACK_TYPE_SUBTITLE)
|
|||
|
reply->writeInt32(mPriData->mCurrentSelectSubTrackIndex);
|
|||
|
else
|
|||
|
logw("invoke: INVOKE_ID_GET_SELECTED_TRACK, trackType(%d) unkown", trackType);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
default:
|
|||
|
{
|
|||
|
logv("unknown invode command %d", nMethodId);
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::setParameter(int key, const Parcel &request)
|
|||
|
{
|
|||
|
logv("setParameter(key=%d)", key);
|
|||
|
(void)key;
|
|||
|
(void)request;
|
|||
|
return OK;
|
|||
|
#if 0
|
|||
|
|
|||
|
switch(key)
|
|||
|
{
|
|||
|
case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
|
|||
|
{
|
|||
|
int nCacheReportIntervalMs;
|
|||
|
|
|||
|
logv("setParameter::KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS");
|
|||
|
|
|||
|
nCacheReportIntervalMs = request.readInt32();
|
|||
|
if(DemuxCompSetCacheStatReportInterval(mPriData->mDemux, nCacheReportIntervalMs) == 0)
|
|||
|
return OK;
|
|||
|
else
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
|
|||
|
{
|
|||
|
logv("setParameter::KEY_PARAMETER_PLAYBACK_RATE_PERMILLE");
|
|||
|
//* TODO.
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
{
|
|||
|
logv("unknown setParameter command %d", key);
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::getParameter(int key, Parcel *reply)
|
|||
|
{
|
|||
|
logv("getParameter");
|
|||
|
(void)(key);
|
|||
|
|
|||
|
(void)(reply);
|
|||
|
return OK;
|
|||
|
|
|||
|
#if 0
|
|||
|
switch(key)
|
|||
|
{
|
|||
|
case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
|
|||
|
{
|
|||
|
logv("getParameter::KEY_PARAMETER_AUDIO_CHANNEL_COUNT");
|
|||
|
//* TODO.
|
|||
|
return OK;
|
|||
|
}
|
|||
|
#if 0// use define CONF_PRODUCT_STB/CONF_CMCC/CONF_YUNOS instead
|
|||
|
case KEY_PARAMETER_GET_CURRENT_BITRATE:
|
|||
|
{
|
|||
|
logd("getParameter::PARAM_KEY_GET_CURRENT_BITRATE");
|
|||
|
if(mPriData->mXPlayer != NULL)
|
|||
|
{
|
|||
|
int currentVideoBitrate = 0;
|
|||
|
int currentAudioBitrate = 0;
|
|||
|
int currentBitrate = 0;
|
|||
|
currentVideoBitrate = PlayerGetVideoBitrate(mPriData->mXPlayer);
|
|||
|
currentAudioBitrate = PlayerGetAudioBitrate(mPriData->mXPlayer);
|
|||
|
currentBitrate = currentVideoBitrate + currentAudioBitrate;
|
|||
|
logd("current Bitrate: video(%d)b/s + audio(%d)b/s = (%d)b/s",
|
|||
|
currentVideoBitrate, currentAudioBitrate, currentBitrate);
|
|||
|
reply->writeInt32(currentBitrate);
|
|||
|
}
|
|||
|
return OK;
|
|||
|
}
|
|||
|
case KEY_PARAMETER_GET_CURRENT_CACHE_DATA_DURATION:
|
|||
|
{
|
|||
|
logv("getParameter::PARAM_KEY_GET_CURRENT_CACHE_DATA_DURATION");
|
|||
|
if(mPriData->mXPlayer != NULL)
|
|||
|
{
|
|||
|
int currentBitrate = 0;
|
|||
|
int currentCacheDataSize = 0;
|
|||
|
int currentCacheDataDuration = 0;
|
|||
|
currentBitrate = PlayerGetVideoBitrate(mPriData->mXPlayer) +
|
|||
|
PlayerGetAudioBitrate(mPriData->mXPlayer);
|
|||
|
currentCacheDataSize = DemuxCompGetCacheSize(mPriData->mDemux);
|
|||
|
|
|||
|
if(currentBitrate <= 0)
|
|||
|
{
|
|||
|
currentCacheDataDuration = 0;
|
|||
|
reply->writeInt32((int)currentCacheDataDuration);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
int64_t tmp = (float)currentCacheDataSize*8.0*1000.0;
|
|||
|
tmp /= (float)currentBitrate;
|
|||
|
currentCacheDataDuration = (int)tmp;
|
|||
|
reply->writeInt32((int)currentCacheDataDuration);
|
|||
|
}
|
|||
|
logd("currentDataSize(%d)B currentBitrate(%d)b/s currentDataDuration(%d)ms",
|
|||
|
currentCacheDataSize, currentBitrate, currentCacheDataDuration);
|
|||
|
}
|
|||
|
return OK;
|
|||
|
}
|
|||
|
#endif
|
|||
|
default:
|
|||
|
{
|
|||
|
loge("unknown getParameter command %d", key);
|
|||
|
return UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
status_t AwPlayer::getMetadata(const media::Metadata::Filter& ids, Parcel *records)
|
|||
|
{
|
|||
|
using media::Metadata;
|
|||
|
|
|||
|
Metadata metadata(records);
|
|||
|
|
|||
|
MediaInfo* mi;
|
|||
|
mi = XPlayerGetMediaInfo(mPriData->mXPlayer);
|
|||
|
|
|||
|
CEDARX_UNUSE(ids);
|
|||
|
|
|||
|
if(mi == NULL)
|
|||
|
{
|
|||
|
return NO_INIT;
|
|||
|
}
|
|||
|
|
|||
|
if(mi->nDurationMs > 0)
|
|||
|
metadata.appendBool(Metadata::kPauseAvailable , true);
|
|||
|
else
|
|||
|
metadata.appendBool(Metadata::kPauseAvailable , false); //* live stream, can not pause.
|
|||
|
|
|||
|
if(mi->bSeekable)
|
|||
|
{
|
|||
|
metadata.appendBool(Metadata::kSeekBackwardAvailable, true);
|
|||
|
metadata.appendBool(Metadata::kSeekForwardAvailable, true);
|
|||
|
metadata.appendBool(Metadata::kSeekAvailable, true);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
metadata.appendBool(Metadata::kSeekBackwardAvailable, false);
|
|||
|
metadata.appendBool(Metadata::kSeekForwardAvailable, false);
|
|||
|
metadata.appendBool(Metadata::kSeekAvailable, false);
|
|||
|
}
|
|||
|
|
|||
|
return OK;
|
|||
|
|
|||
|
//* other metadata in include/media/Metadata.h, Keep in sync with android/media/Metadata.java.
|
|||
|
/*
|
|||
|
Metadata::kTitle; // String
|
|||
|
Metadata::kComment; // String
|
|||
|
Metadata::kCopyright; // String
|
|||
|
Metadata::kAlbum; // String
|
|||
|
Metadata::kArtist; // String
|
|||
|
Metadata::kAuthor; // String
|
|||
|
Metadata::kComposer; // String
|
|||
|
Metadata::kGenre; // String
|
|||
|
Metadata::kDate; // Date
|
|||
|
Metadata::kDuration; // Integer(millisec)
|
|||
|
Metadata::kCdTrackNum; // Integer 1-based
|
|||
|
Metadata::kCdTrackMax; // Integer
|
|||
|
Metadata::kRating; // String
|
|||
|
Metadata::kAlbumArt; // byte[]
|
|||
|
Metadata::kVideoFrame; // Bitmap
|
|||
|
|
|||
|
Metadata::kBitRate; // Integer, Aggregate rate of
|
|||
|
Metadata::kAudioBitRate; // Integer, bps
|
|||
|
Metadata::kVideoBitRate; // Integer, bps
|
|||
|
Metadata::kAudioSampleRate; // Integer, Hz
|
|||
|
Metadata::kVideoframeRate; // Integer, Hz
|
|||
|
|
|||
|
// See RFC2046 and RFC4281.
|
|||
|
Metadata::kMimeType; // String
|
|||
|
Metadata::kAudioCodec; // String
|
|||
|
Metadata::kVideoCodec; // String
|
|||
|
|
|||
|
Metadata::kVideoHeight; // Integer
|
|||
|
Metadata::kVideoWidth; // Integer
|
|||
|
Metadata::kNumTracks; // Integer
|
|||
|
Metadata::kDrmCrippled; // Boolean
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::setSubCharset(const char* strFormat)
|
|||
|
{
|
|||
|
if(strFormat != NULL)
|
|||
|
{
|
|||
|
int i;
|
|||
|
for(i=0; strTextCodecFormats[i]; i++)
|
|||
|
{
|
|||
|
if(!strcmp(strTextCodecFormats[i], strFormat))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if(strTextCodecFormats[i] != NULL)
|
|||
|
strcpy(mPriData->mDefaultTextFormat, strTextCodecFormats[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
strcpy(mPriData->mDefaultTextFormat, "UTF-8");
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::getSubCharset(char *charset)
|
|||
|
{
|
|||
|
if(mPriData->mXPlayer == NULL)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
strcpy(charset, mPriData->mDefaultTextFormat);
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::setSubDelay(int nTimeMs)
|
|||
|
{
|
|||
|
if(mPriData->mXPlayer == NULL)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
return XPlayerSetSubDelay(mPriData->mXPlayer, nTimeMs);
|
|||
|
}
|
|||
|
|
|||
|
int AwPlayer::getSubDelay()
|
|||
|
{
|
|||
|
if(mPriData->mXPlayer == NULL)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
return XPlayerGetSubDelay(mPriData->mXPlayer);
|
|||
|
}
|
|||
|
|
|||
|
status_t AwPlayer::callbackProcess(int messageId, int ext1, void* param)
|
|||
|
{
|
|||
|
switch(messageId)
|
|||
|
{
|
|||
|
case AWPLAYER_MEDIA_PREPARED:
|
|||
|
{
|
|||
|
|
|||
|
#if BUFFERING_ICON_BUG
|
|||
|
if (!mPriData->mbIsDiagnose &&
|
|||
|
mPriData->mConfigInfo.appType == APP_CMCC_WASU)
|
|||
|
{
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
|
|||
|
}
|
|||
|
#endif
|
|||
|
sendEvent(MEDIA_PREPARED, 0, 0);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_PLAYBACK_COMPLETE:
|
|||
|
{
|
|||
|
sendEvent(MEDIA_PLAYBACK_COMPLETE, 0, 0);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_SEEK_COMPLETE:
|
|||
|
{
|
|||
|
sendEvent(MEDIA_SEEK_COMPLETE, 0, 0);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_LOG_RECORDER:
|
|||
|
{
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
logv("AwLogRecorderRecord %s.", (char*)param);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, (char*)param);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_BUFFERING_UPDATE:
|
|||
|
{
|
|||
|
int nTotalPercentage;
|
|||
|
int nBufferPercentage;
|
|||
|
int nLoadingPercentage;
|
|||
|
|
|||
|
nTotalPercentage = ((int*)param)[0]; //* read positon to total file size.
|
|||
|
nBufferPercentage = ((int*)param)[1]; //* cache buffer fullness.
|
|||
|
nLoadingPercentage = ((int*)param)[2]; //* loading percentage to start play.
|
|||
|
sendEvent(MEDIA_BUFFERING_UPDATE, nTotalPercentage,
|
|||
|
nBufferPercentage<<16 | nLoadingPercentage);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_ERROR:
|
|||
|
{
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[error][%s %s %d]Error happened, event: %d",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, ext1);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONF_PRODUCT_STB)
|
|||
|
if(ext1 == AW_MEDIA_ERROR_UNKNOWN)
|
|||
|
sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, 0);
|
|||
|
else if(ext1 == AW_MEDIA_ERROR_IO)
|
|||
|
sendEvent(MEDIA_ERROR, MEDIA_ERROR_IO, 0);
|
|||
|
else if(ext1 == AW_MEDIA_ERROR_UNSUPPORTED)
|
|||
|
sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNSUPPORTED, 0);
|
|||
|
else
|
|||
|
{
|
|||
|
logw("unkown ext1: %d", ext1);
|
|||
|
sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, 0);
|
|||
|
}
|
|||
|
#else
|
|||
|
sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, 0);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_INFO:
|
|||
|
{
|
|||
|
switch(ext1)
|
|||
|
{
|
|||
|
case AW_MEDIA_INFO_UNKNOWN:
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_UNKNOWN);
|
|||
|
break;
|
|||
|
case AW_MEDIA_INFO_RENDERING_START:
|
|||
|
{
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
struct timeval tv;
|
|||
|
int64_t renderTimeMs;
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
renderTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]show the first video frame,"
|
|||
|
" spend time: %lldms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__,
|
|||
|
(long long int)(renderTimeMs - mPriData->mPlayTimeMs));
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
|
|||
|
sendEvent(MEDIA_STARTED, 0, 0);
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_MEDIA_INFO_BUFFERING_START:
|
|||
|
{
|
|||
|
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
int *pNeedBufferSize = (int*)param;
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]buffering start, "
|
|||
|
"need buffer data size: %.2fMB",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__,
|
|||
|
*pNeedBufferSize/(1024*1024.0f));
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
struct timeval tv;
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
mPriData->mBufferTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
}
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_MEDIA_INFO_BUFFERING_END:
|
|||
|
{
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
struct timeval tv;
|
|||
|
gettimeofday(&tv, NULL);
|
|||
|
int64_t bufferEndTimeMs = (tv.tv_sec * 1000000ll + tv.tv_usec)/1000;
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]buffering end, lasting time: %lldms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__,
|
|||
|
(long long int)(bufferEndTimeMs - mPriData->mBufferTimeMs));
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_MEDIA_INFO_NOT_SEEKABLE:
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0);
|
|||
|
break;
|
|||
|
|
|||
|
#if defined(CONF_PRODUCT_STB)
|
|||
|
case AW_MEDIA_INFO_DOWNLOAD_START:
|
|||
|
{
|
|||
|
DownloadObject* obj = (DownloadObject*)param;
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]ts segment download is start, "
|
|||
|
"number: %d, filesize: %.2fMB, duration: %lldms",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__, obj->seqNum,
|
|||
|
(float)obj->seqSize/(1024*1024.0f), obj->seqDuration/1000);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_DOWNLOAD_START, obj->seqNum);
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_MEDIA_INFO_DOWNLOAD_END:
|
|||
|
{
|
|||
|
DownloadObject* obj = (DownloadObject*)param;
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[info][%s %s %d]ts segment download is complete, "
|
|||
|
"recvsize: %.2fMB, spend time: %lldms, rate: %lldbps",
|
|||
|
LOG_TAG, __FUNCTION__, __LINE__,
|
|||
|
(float)obj->seqSize/(1024*1024.0f),
|
|||
|
obj->spendTime, obj->rate);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_DOWNLOAD_END, (int)obj->spendTime);
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_MEDIA_INFO_DOWNLOAD_ERROR:
|
|||
|
{
|
|||
|
DownloadObject* obj = (DownloadObject*)param;
|
|||
|
if(mPriData->mLogRecorder != NULL)
|
|||
|
{
|
|||
|
char cmccLog[4096] = "";
|
|||
|
sprintf(cmccLog, "[error][%s %s %d]Error happened, event: %d", LOG_TAG,
|
|||
|
__FUNCTION__, __LINE__, MEDIA_INFO_DOWNLOAD_ERROR);
|
|||
|
logv("AwLogRecorderRecord %s.", cmccLog);
|
|||
|
AwLogRecorderRecord(mPriData->mLogRecorder, cmccLog);
|
|||
|
}
|
|||
|
|
|||
|
sendEvent(MEDIA_INFO, MEDIA_INFO_DOWNLOAD_ERROR, obj->statusCode);
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
default:
|
|||
|
logw("unkown info msg");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
#if !(defined(CONF_NEW_BDMV_STREAM))
|
|||
|
case AWPLAYER_EXTEND_MEDIA_INFO:
|
|||
|
{
|
|||
|
switch(ext1)
|
|||
|
{
|
|||
|
case AW_EX_IOREQ_ACCESS:
|
|||
|
{
|
|||
|
char *filePath = (char *)((uintptr_t *)param)[0];
|
|||
|
int mode = ((uintptr_t *)param)[1];
|
|||
|
int *pRet = (int *)((uintptr_t *)param)[2];
|
|||
|
|
|||
|
Parcel parcel;
|
|||
|
Parcel replyParcel;
|
|||
|
*pRet = -1;
|
|||
|
|
|||
|
// write path string as a byte array
|
|||
|
parcel.writeInt32(strlen(filePath));
|
|||
|
parcel.write(filePath, strlen(filePath));
|
|||
|
parcel.writeInt32(mode);
|
|||
|
sendEvent(AWEXTEND_MEDIA_INFO,
|
|||
|
AWEXTEND_MEDIA_INFO_CHECK_ACCESS_RIGHRS,
|
|||
|
0, &parcel, &replyParcel);
|
|||
|
replyParcel.setDataPosition(0);
|
|||
|
*pRet = replyParcel.readInt32();
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_EX_IOREQ_OPEN:
|
|||
|
{
|
|||
|
char *filePath = (char *)((uintptr_t *)param)[0];
|
|||
|
int *pFd = (int *)((uintptr_t *)param)[1];
|
|||
|
int fd = -1;
|
|||
|
|
|||
|
Parcel parcel;
|
|||
|
Parcel replyParcel;
|
|||
|
bool bFdValid = false;
|
|||
|
|
|||
|
*pFd = -1;
|
|||
|
|
|||
|
// write path string as a byte array
|
|||
|
parcel.writeInt32(strlen(filePath));
|
|||
|
parcel.write(filePath, strlen(filePath));
|
|||
|
sendEvent(AWEXTEND_MEDIA_INFO,
|
|||
|
AWEXTEND_MEDIA_INFO_REQUEST_OPEN_FILE,
|
|||
|
0, &parcel, &replyParcel);
|
|||
|
replyParcel.setDataPosition(0);
|
|||
|
bFdValid = replyParcel.readInt32();
|
|||
|
if (bFdValid == true)
|
|||
|
{
|
|||
|
fd = replyParcel.readFileDescriptor();
|
|||
|
if (fd < 0)
|
|||
|
{
|
|||
|
loge("invalid fd '%d'", fd);
|
|||
|
*pFd = -1;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*pFd = dup(fd);
|
|||
|
if (*pFd < 0)
|
|||
|
{
|
|||
|
loge("dup fd failure, errno(%d) '%d'", errno, fd);
|
|||
|
}
|
|||
|
close(fd);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_EX_IOREQ_OPENDIR:
|
|||
|
{
|
|||
|
char *dirPath = (char *)((uintptr_t *)param)[0];
|
|||
|
int *pDirId = (int *)((uintptr_t *)param)[1];
|
|||
|
|
|||
|
Parcel parcel;
|
|||
|
Parcel replyParcel;
|
|||
|
|
|||
|
*pDirId = -1;
|
|||
|
|
|||
|
// write path string as a byte array
|
|||
|
parcel.writeInt32(strlen(dirPath));
|
|||
|
parcel.write(dirPath, strlen(dirPath));
|
|||
|
sendEvent(AWEXTEND_MEDIA_INFO,
|
|||
|
AWEXTEND_MEDIA_INFO_REQUEST_OPEN_DIR,
|
|||
|
0, &parcel, &replyParcel);
|
|||
|
replyParcel.setDataPosition(0);
|
|||
|
*pDirId = replyParcel.readInt32();
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_EX_IOREQ_READDIR:
|
|||
|
{
|
|||
|
int dirId = ((uintptr_t *)param)[0];
|
|||
|
int *pRet = (int *)((uintptr_t *)param)[1];
|
|||
|
char *buf = (char *)((uintptr_t *)param)[2];
|
|||
|
int bufLen = ((uintptr_t *)param)[3];
|
|||
|
loge("** aw-read-dir: dirId = %d, buf = %p, bufLen = %d",
|
|||
|
dirId,buf,bufLen);
|
|||
|
Parcel parcel;
|
|||
|
Parcel replyParcel;
|
|||
|
int fileNameLen = -1;
|
|||
|
int32_t replyRet = -1;
|
|||
|
|
|||
|
*pRet = -1;
|
|||
|
|
|||
|
// write path string as a byte array
|
|||
|
parcel.writeInt32(dirId);
|
|||
|
sendEvent(AWEXTEND_MEDIA_INFO, AWEXTEND_MEDIA_INFO_REQUEST_READ_DIR,
|
|||
|
0, &parcel, &replyParcel);
|
|||
|
replyParcel.setDataPosition(0);
|
|||
|
replyRet = replyParcel.readInt32();
|
|||
|
|
|||
|
if (0 == replyRet)
|
|||
|
{
|
|||
|
fileNameLen = replyParcel.readInt32();
|
|||
|
if (fileNameLen > 0 && fileNameLen < bufLen)
|
|||
|
{
|
|||
|
const char* strdata = (const char*)replyParcel.readInplace(fileNameLen);
|
|||
|
memcpy(buf, strdata, fileNameLen);
|
|||
|
buf[fileNameLen] = 0;
|
|||
|
*pRet = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case AW_EX_IOREQ_CLOSEDIR:
|
|||
|
{
|
|||
|
int dirId = ((uintptr_t *)param)[0];
|
|||
|
int *pRet = (int *)((uintptr_t *)param)[1];
|
|||
|
|
|||
|
Parcel parcel;
|
|||
|
Parcel replyParcel;
|
|||
|
|
|||
|
// write path string as a byte array
|
|||
|
parcel.writeInt32(dirId);
|
|||
|
sendEvent(AWEXTEND_MEDIA_INFO,
|
|||
|
AWEXTEND_MEDIA_INFO_REQUEST_CLOSE_DIR,
|
|||
|
0, &parcel, &replyParcel);
|
|||
|
replyParcel.setDataPosition(0);
|
|||
|
*pRet = replyParcel.readInt32();
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
case SUBCTRL_SUBTITLE_AVAILABLE:
|
|||
|
{
|
|||
|
Parcel parcel;
|
|||
|
unsigned int nSubtitleId = (unsigned int)((uintptr_t*)param)[0];
|
|||
|
SubtitleItem* pSubtitleItem = (SubtitleItem*)((uintptr_t*)param)[1];
|
|||
|
|
|||
|
logd("subtitle available. id = %d, pSubtitleItem = %p",nSubtitleId,pSubtitleItem);
|
|||
|
if(pSubtitleItem == NULL)
|
|||
|
{
|
|||
|
logw("pSubtitleItem == NULL");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
mPriData->mIsSubtitleInTextFormat = !!pSubtitleItem->bText; //* 0 or 1.
|
|||
|
|
|||
|
if(mPriData->mIsSubtitleDisable == 0)
|
|||
|
{
|
|||
|
if(mPriData->mIsSubtitleInTextFormat)
|
|||
|
{
|
|||
|
SubtitleUtilsFillTextSubtitleToParcel(&parcel,
|
|||
|
pSubtitleItem,
|
|||
|
nSubtitleId,
|
|||
|
mPriData->mDefaultTextFormat,
|
|||
|
&mPriData->mIsFirstItem);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
sendEvent(MEDIA_TIMED_TEXT); //* clear bmp subtitle first
|
|||
|
SubtitleUtilsFillBitmapSubtitleToParcel(&parcel, pSubtitleItem, nSubtitleId);
|
|||
|
}
|
|||
|
//*record subtitile id
|
|||
|
mPriData->mSubtitleDisplayIds[mPriData->mSubtitleDisplayIdsUpdateIndex] =
|
|||
|
nSubtitleId;
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex++;
|
|||
|
if(mPriData->mSubtitleDisplayIdsUpdateIndex>=64)
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
|
|||
|
logd("notify available message.");
|
|||
|
sendEvent(MEDIA_TIMED_TEXT, 0, 0, &parcel);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case SUBCTRL_SUBTITLE_EXPIRED:
|
|||
|
{
|
|||
|
logd("subtitle expired.");
|
|||
|
Parcel parcel;
|
|||
|
unsigned int nSubtitleId;
|
|||
|
int i;
|
|||
|
nSubtitleId = *(unsigned int*)param;
|
|||
|
|
|||
|
if(mPriData->mIsSubtitleDisable == 0)
|
|||
|
{
|
|||
|
//* match the subtitle id which is displaying ,or we may clear null subtitle
|
|||
|
for(i=0;i<64;i++)
|
|||
|
{
|
|||
|
if(nSubtitleId==mPriData->mSubtitleDisplayIds[i])
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if(i!=64)
|
|||
|
{
|
|||
|
mPriData->mSubtitleDisplayIds[i] = 0xffffffff;
|
|||
|
if(mPriData->mIsSubtitleInTextFormat == 1)
|
|||
|
{
|
|||
|
//* set subtitle id
|
|||
|
parcel.writeInt32(KEY_GLOBAL_SETTING);
|
|||
|
|
|||
|
//* nofity app to hide this subtitle
|
|||
|
parcel.writeInt32(KEY_STRUCT_AWEXTEND_HIDESUB);
|
|||
|
parcel.writeInt32(1);
|
|||
|
parcel.writeInt32(KEY_SUBTITLE_ID);
|
|||
|
parcel.writeInt32(nSubtitleId);
|
|||
|
|
|||
|
logd("notify text expired message.");
|
|||
|
sendEvent(MEDIA_TIMED_TEXT, 0, 0, &parcel);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//* clear the mSubtitleDisplayIds
|
|||
|
memset(mPriData->mSubtitleDisplayIds,0xff,64*sizeof(unsigned int));
|
|||
|
mPriData->mSubtitleDisplayIdsUpdateIndex = 0;
|
|||
|
//* if the sub is bmp ,we just send "clear all" command,
|
|||
|
//* nSubtitleId is not sent.
|
|||
|
logd("notify subtitle expired message.");
|
|||
|
sendEvent(MEDIA_TIMED_TEXT);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case AWPLAYER_MEDIA_SET_VIDEO_SIZE:
|
|||
|
{
|
|||
|
int nWidth = ((int*)param)[0];
|
|||
|
int nHeight = ((int*)param)[1];
|
|||
|
|
|||
|
logd("=== set videosize (%d, %d)", nWidth, nHeight);
|
|||
|
sendEvent(MEDIA_SET_VIDEO_SIZE, nWidth, nHeight);
|
|||
|
break;
|
|||
|
}
|
|||
|
#if (CONF_ANDROID_MAJOR_VER > 6)
|
|||
|
case AWPLAYER_MEDIA_META_DATA:
|
|||
|
{
|
|||
|
Parcel parcel;
|
|||
|
int size;
|
|||
|
char* buffer;
|
|||
|
int64_t timeUs = ((unsigned int*)param)[0];
|
|||
|
timeUs <<= 32;
|
|||
|
timeUs |= ((unsigned int*)param)[1];
|
|||
|
size = ((int*)param)[2];
|
|||
|
buffer = (char*)((unsigned int*)param)[3];
|
|||
|
parcel.writeInt64(timeUs);
|
|||
|
parcel.writeInt32(size);
|
|||
|
parcel.writeInt32(size);
|
|||
|
parcel.write(buffer, size);
|
|||
|
|
|||
|
logv("notify meta data message.");
|
|||
|
sendEvent(MEDIA_META_DATA, 0, 0, &parcel);
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
default:
|
|||
|
{
|
|||
|
logw("message 0x%x not handled.", messageId);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return OK;
|
|||
|
}
|
|||
|
|
|||
|
static int XPlayerCallbackProcess(void* pUser, int eMessageId, int ext1, void* param)
|
|||
|
{
|
|||
|
AwPlayer *p = (AwPlayer*)pUser;
|
|||
|
p->callbackProcess(eMessageId, ext1, param);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
static int SubCallbackProcess(void* pUser, int eMessageId, void* param)
|
|||
|
{
|
|||
|
AwPlayer* p = (AwPlayer*)pUser;
|
|||
|
|
|||
|
p->callbackProcess(eMessageId, 0, param);
|
|||
|
|
|||
|
return 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
static int GetCallingApkName(char* strApkName, int nMaxNameSize)
|
|||
|
{
|
|||
|
int fd;
|
|||
|
|
|||
|
snprintf(strApkName, nMaxNameSize, "/proc/%d/cmdline",
|
|||
|
IPCThreadState::self()->getCallingPid());
|
|||
|
fd = ::open(strApkName, O_RDONLY);
|
|||
|
strApkName[0] = '\0';
|
|||
|
if (fd >= 0)
|
|||
|
{
|
|||
|
strApkName[nMaxNameSize - 1] = '\0';
|
|||
|
::read(fd, strApkName, nMaxNameSize - 1);
|
|||
|
::close(fd);
|
|||
|
logd("Calling process is: %s", strApkName);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void enableMediaBoost(MediaInfo* mi)
|
|||
|
{
|
|||
|
char cmd[PROP_VALUE_MAX] = {0};
|
|||
|
int total = 0;
|
|||
|
struct ScMemOpsS *memops = NULL;
|
|||
|
|
|||
|
if(mi == NULL || mi->pVideoStreamInfo == NULL)
|
|||
|
{
|
|||
|
logd("input invalid args.");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CONF_MEDIA_BOOST_MEM)
|
|||
|
if(mi->pVideoStreamInfo->bSecureStreamFlagLevel1 == 1)
|
|||
|
{
|
|||
|
memops = SecureMemAdapterGetOpsS();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
memops = MemAdapterGetOpsS();
|
|||
|
}
|
|||
|
CdcMemOpen(memops);
|
|||
|
total = CdcMemTotalSize(memops);
|
|||
|
CdcMemClose(memops);
|
|||
|
|
|||
|
//set the mem property
|
|||
|
if((mi->pVideoStreamInfo->nWidth >= WIDTH_4K || mi->pVideoStreamInfo->nHeight >= HEIGHT_4K)
|
|||
|
&& total < 190000 )
|
|||
|
{
|
|||
|
sprintf(cmd, "model%d:3", getpid());
|
|||
|
logd("setprop media.boost.pref %s", cmd);
|
|||
|
property_set("media.boost.pref", cmd);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//setprop media.boost.pref mode123:0:c:num
|
|||
|
//attention!!! Just for h5, num(1,2,3,4) lock cpu num; num(5) lock freq.
|
|||
|
#if defined(CONF_MEDIA_BOOST_CPU)
|
|||
|
sprintf(cmd, "mode%d:0:c:5", getpid());
|
|||
|
logd("setprop media.boost.pref %s", cmd);
|
|||
|
property_set("media.boost.pref", cmd);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
void disableMediaBoost()
|
|||
|
{
|
|||
|
char value[PROP_VALUE_MAX] = {0};
|
|||
|
|
|||
|
property_get("media.boost.pref", value, "0");
|
|||
|
|
|||
|
size_t len = strlen(value);
|
|||
|
if (len > 1 && value[len - 1] > '0')
|
|||
|
{
|
|||
|
value[len - 1] = '0';
|
|||
|
logd("setprop media.boost.pref %s", value);
|
|||
|
property_set("media.boost.pref", value);
|
|||
|
}
|
|||
|
}
|