www.pudn.com > videoplayer.rar > AmlogicPlayer.cpp, change:2011-03-04,size:17388b


/* 
** 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. 
*/ 
 
#define LOG_NDEBUG 0 
#define LOG_TAG "AmlogicPlayer" 
#include "utils/Log.h" 
 
#include <stdio.h> 
#include <assert.h> 
#include <limits.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sched.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <surfaceflinger/ISurface.h> 
#include <ui/Overlay.h> 
 
#include <adecproc.h> 
#include <cutils/properties.h> 
 
extern int android_datasource_init(void); 
 
#include "AmlogicPlayer.h" 
#ifndef FBIOPUT_OSD_SRCCOLORKEY 
#define  FBIOPUT_OSD_SRCCOLORKEY    0x46fb 
#endif 
 
#ifndef FBIOPUT_OSD_SRCKEY_ENABLE 
#define  FBIOPUT_OSD_SRCKEY_ENABLE  0x46fa 
#endif 
 
#ifndef FBIOPUT_OSD_SET_GBL_ALPHA 
#define  FBIOPUT_OSD_SET_GBL_ALPHA	0x4500 
#endif 
 
 
#ifdef HAVE_GETTID 
static pid_t myTid() { return gettid(); } 
#else 
static pid_t myTid() { return getpid(); } 
#endif 
 
// ---------------------------------------------------------------------------- 
 
namespace android { 
 
// ---------------------------------------------------------------------------- 
 
// TODO: Determine appropriate return codes 
static status_t ERROR_NOT_OPEN = -1; 
static status_t ERROR_OPEN_FAILED = -2; 
static status_t ERROR_ALLOCATE_FAILED = -4; 
static status_t ERROR_NOT_SUPPORTED = -8; 
static status_t ERROR_NOT_READY = -16; 
static status_t STATE_INIT = 0; 
static status_t STATE_ERROR = 1; 
static status_t STATE_OPEN = 2; 
 
static URLProtocol android_protocol; 
 
#define MID_800_400_FREESC	(0x10001) 
 
AmlogicPlayer::AmlogicPlayer() : 
    mPlayTime(0), mDuration(0), mState(STATE_ERROR), 
    mStreamType(-1), mLoop(false),  
    mExit(false), mPaused(false), mRender(false), mRenderTid(-1), 
    mPlayer_id(-1), 
    mWidth(0), 
    mHeight(0), 
    mhasVideo(false), 
    mhasAudio(false), 
    mIgnoreMsg(false) 
{ 
	Mutex::Autolock l(mMutex); 
    LOGV("AmlogicPlayer constructor\n"); 
    memset(&mAmlogicFile, 0, sizeof mAmlogicFile); 
	memset(&mPlay_ctl,0,sizeof mPlay_ctl); 
	 
} 
 
status_t AmlogicPlayer::BasicInit() 
{ 
	static int have_inited=0; 
	if(!have_inited) 
	{ 
		player_init(); 
		URLProtocol *prot=&android_protocol; 
		prot->name="android"; 
	    prot->url_open=(int (*)(URLContext *, const char *, int ))vp_open; 
	    prot->url_read=(int (*)(URLContext *, unsigned char *, int))vp_read; 
	    prot->url_write=(int (*)(URLContext *, unsigned char *, int))vp_write; 
	    prot->url_seek=(int64_t (*)(URLContext *, int64_t , int))vp_seek; 
	    prot->url_close=(int (*)(URLContext *))vp_close; 
	    prot->url_get_file_handle = (int (*)(URLContext *))vp_get_file_handle; 
		av_register_protocol(prot); 
		have_inited++; 
	} 
	return 0; 
} 
 
 
 
 bool AmlogicPlayer::PropIsEnable(const char* str) 
{  
	char value[PROPERTY_VALUE_MAX]; 
	if(property_get(str, value, NULL)>0) 
	{ 
		if ((!strcmp(value, "1") || !strcmp(value, "true"))) 
		{ 
			LOGI("%s is enabled\n",str); 
			return true; 
		} 
	} 
	LOGI("%s is disabled\n",str); 
	return false; 
} 
 
status_t AmlogicPlayer::exitAllThreads() 
{ 
	AmlogicPlayer::BasicInit(); 
	pid_info_t playerinfo; 
 
	player_list_allpid(&playerinfo); 
	LOGI("found %d not exit player threads,try exit it now\n",playerinfo.num); 
	if(playerinfo.num>0) 
	{ 
		int i; 
		for(i=0;i<playerinfo.num;i++) 
			{ 
			//player_exit(playerinfo.pid[i]); 
			} 
	} 
	return NO_ERROR; 
} 
 
void AmlogicPlayer::onFirstRef() 
{ 
	Mutex::Autolock l(mMutex); 
    LOGV("onFirstRef"); 
	AmlogicPlayer::BasicInit(); 
	AmlogicPlayer::exitAllThreads(); 
	av_log_set_level(50); 
    // create playback thread 
    mState = STATE_INIT; 
} 
 
status_t AmlogicPlayer::initCheck() 
{ 
	Mutex::Autolock l(mMutex); 
	LOGV("initCheck"); 
    if (mState != STATE_ERROR)  
			return NO_ERROR; 
    return ERROR_NOT_READY; 
} 
 
int set_sys_int(char *path,int val) 
{ 
    	int fd; 
        char  bcmd[16]; 
        fd=open(path, O_CREAT|O_RDWR | O_TRUNC, 0644); 
        if(fd>=0) 
        { 
        	sprintf(bcmd,"%d",val); 
        	write(fd,bcmd,strlen(bcmd)); 
        	close(fd); 
        	return 0; 
        } 
	LOGV("set fs%s=%d failed\n",path); 
        return -1; 
} 
#define DISABLE_VIDEO "/sys/class/video/disable_video" 
void  
AmlogicPlayer::VideoViewOn(void) 
{ 
	int ret=0; 
	disable_freescale(MID_800_400_FREESC); 
    	ret=player_video_overlay_en(1); 
	LOGV("VideoViewOn=%d\n",ret); 
	//OsdBlank("/sys/class/graphics/fb0/blank",1); 
	set_sys_int(DISABLE_VIDEO,0); 
} 
void  
AmlogicPlayer::VideoViewClose(void) 
{ 
	int ret=0; 
    	ret=player_video_overlay_en(0); 
	enable_freescale(MID_800_400_FREESC); 
	LOGV("VideoViewClose=%d\n",ret); 
	//OsdBlank("/sys/class/graphics/fb0/blank",0); 
	set_sys_int(DISABLE_VIDEO,1); 
} 
 
 
AmlogicPlayer::~AmlogicPlayer() { 
    LOGV("AmlogicPlayer destructor\n"); 
	Mutex::Autolock l(mMutex); 
    release(); 
	 
    if (mOverlay.get() != NULL) { 
        LOGV("Overlay destroy %p", &mOverlay); 
 
        mOverlay->destroy(); 
        mOverlay.clear(); 
 
        sleep(1); 
    } 
} 
 
status_t AmlogicPlayer::setDataSource( 
        const char *uri, const KeyedVector<String8, String8> *headers)  
{ 
    LOGV("setDataSource"); 
    return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL, headers); // intentionally less than LONG_MAX 
} 
 
 
status_t AmlogicPlayer::setDataSource(int fd, int64_t offset, int64_t length) 
{	 
	LOGV("setDataSource,fd=%d,offset=%lld,len=%lld,not finished\n",fd,offset,length); 
	return setdatasource(NULL,fd,offset,length, NULL); 
} 
 
int AmlogicPlayer::vp_open(URLContext *h, const char *filename, int flags) 
{	 
	/* 
	sprintf(file,"android:AmlogicPlayer=[%x:%x],AmlogicPlayer_fd=[%x:%x]", 
	*/ 
	LOGV("vp_open=%s\n",filename); 
	if(strncmp(filename,"android",strlen("android"))==0) 
	{	 
		unsigned int fd=0,fd1=0; 
		char *str=strstr(filename,"AmlogicPlayer_fd"); 
		if(str==NULL) 
			return -1; 
		sscanf(str,"AmlogicPlayer_fd=[%x:%x]\n",(unsigned int*)&fd,(unsigned int*)&fd1); 
		if(fd!=0 && ((unsigned int)fd1==~(unsigned int)fd)) 
		{ 
			h->priv_data=(void*) fd; 
			if(h->priv_data!=0) 
			{ 
				LOGV("android_open %s OK,h->priv_data=%p\n",filename,h->priv_data); 
				return 0; 
			} 
			else 
			{ 
				LOGV("android_open %s Faild\n",filename); 
				return -1; 
			} 
		} 
	} 
	return -1; 
} 
 
int AmlogicPlayer::vp_read(URLContext *h, unsigned char *buf, int size) 
{	 
	FILE* fp= (FILE*)h->priv_data; 
	int ret; 
	LOGV("%s,player=%p\n",__FUNCTION__,fp); 
	ret=fread(buf,1,size,fp); 
	LOGV("%s,size=%d,ret=%d\n",__FUNCTION__,size,ret); 
	return ret; 
} 
 
int AmlogicPlayer::vp_write(URLContext *h, unsigned char *buf, int size) 
{	 
	FILE *fp= (FILE*)h->priv_data; 
	LOGV("%s\n",__FUNCTION__); 
	return -1; 
} 
int64_t AmlogicPlayer::vp_seek(URLContext *h, int64_t pos, int whence) 
{ 
	FILE*  fp= (FILE*)h->priv_data; 
	LOGV("%s\n",__FUNCTION__); 
	if (whence == AVSEEK_SIZE) 
		{ 
		int64_t pos=ftell(fp); 
		int64_t len; 
		fseek(fp,0,SEEK_END); 
		len=ftell(fp); 
		fseek(fp,pos,SEEK_SET); 
		return len; 
		} 
	return fseek(fp, pos, whence); 
} 
 
 
int AmlogicPlayer::vp_close(URLContext *h) 
{ 
	FILE* fp= (FILE*)h->priv_data; 
	LOGV("%s\n",__FUNCTION__); 
	return 0; /*don't close file here*/ 
	//return fclose(fp); 
} 
 
int AmlogicPlayer::vp_get_file_handle(URLContext *h) 
{ 
	LOGV("%s\n",__FUNCTION__); 
    return (intptr_t) h->priv_data; 
} 
 
 
 
 
int AmlogicPlayer::updateprocess(int pid,player_info_t *info) 
{ 
	AmlogicPlayer *player =(AmlogicPlayer *)player_get_extern_priv(pid); 
	if(player) 
		return player->UpdateProcess(pid,info); 
	else 
		return -1; 
} 
 
int AmlogicPlayer::UpdateProcess(int pid,player_info_t *info) 
{ 
 
	LOGV("update_process pid=%d, current=%d,status=[%s]\n", pid, info->current_time,player_status2str(info->status)); 
	if(mIgnoreMsg)	 
		return 0; 
	if( info->status==PLAYER_INITING  	||  
		info->status==PLAYER_BUFFERING 	|| 
		info->status==PLAYER_SEARCHING) 
	{ 
		sendEvent(MEDIA_BUFFERING_UPDATE,0); 
	} 
	else if(info->status==PLAYER_INITOK) 
	{	 
		updateMediaInfo(); 
		sendEvent(MEDIA_PREPARED); 
		sendEvent(MEDIA_SET_VIDEO_SIZE,mWidth,mHeight); 
		 
	} 
	if(info->status==PLAYER_STOPED || info->status==PLAYER_PLAYEND) 
	{ 
		sendEvent(MEDIA_PLAYBACK_COMPLETE); 
	} 
	else if(info->status==PLAYER_ERROR) 
	{ 
		sendEvent(MEDIA_ERROR,MEDIA_ERROR_UNKNOWN,info->error_no); 
		//sendEvent(MEDIA_ERROR,MEDIA_ERROR_UNKNOWN,info->error_no); 
	} 
	else 
	{ 
		if(info->status==PLAYER_SEARCHOK) 
		{ 
			sendEvent(MEDIA_SEEK_COMPLETE); 
		} 
		if(info->full_time!=-1) 
			mDuration=info->full_time*1000; 
		if(info->current_time!=-1) 
		 	mPlayTime=info->current_time*1000; 
		  
	} 
 
	 return 0; 
} 
 
status_t AmlogicPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length, const KeyedVector<String8, String8> *headers) 
{ 
	int num; 
  	char * file=NULL; 
 
	if(path==NULL) 
	{ 
		if(fd<0 || offset<0) 
			return -1; 
		file=(char *)malloc(128); 
		if(file==NULL) 
			return NO_MEMORY; 
		mAmlogicFile.oldfd=fd; 
		mAmlogicFile.mFile = fdopen(dup(fd), "r"); 
		mAmlogicFile.mOffset=offset; 
		mAmlogicFile.mLength=length; 
		mPlay_ctl.t_pos=-1;/*don't seek to 0*/ 
		//mPlay_ctl.t_pos=0;/*don't seek to 0*/ 
		fseek(mAmlogicFile.mFile , offset, SEEK_SET); 
		sprintf(file,"android:AmlogicPlayer=[%x:%x],AmlogicPlayer_fd=[%x:%x]", 
					(unsigned int)this,(~(unsigned int)this), 
					(unsigned int)mAmlogicFile.mFile,(~(unsigned int)mAmlogicFile.mFile)); 
	} 
	else 
	{ 
		file=(char *)malloc(strlen(path)+4); 
		if(file==NULL) 
			return NO_MEMORY; 
		if(strncmp(path,"http",strlen("http"))==0) 
			{	/*http-->shttp*/ 
				num=sprintf(file,"s%s",path); 
				file[num]='\0'; 
			} 
		else 
			{ 
				num=sprintf(file,"%s",path); 
				file[num]='\0'; 
			} 
		mPlay_ctl.t_pos=0; 
        if (mPlay_ctl.headers) { 
            free(mPlay_ctl.headers); 
            mPlay_ctl.headers = NULL; 
        } 
        if (headers) { 
            //one huge string of the HTTP headers to add 
            int len = 0; 
            for (size_t i = 0; i < headers->size(); ++i) { 
                len += strlen(headers->keyAt(i)); 
                len += strlen(": "); 
                len += strlen(headers->valueAt(i)); 
                len += strlen("\r\n"); 
            } 
            len += 1; 
            mPlay_ctl.headers = (char *)malloc(len); 
            if (mPlay_ctl.headers) { 
                mPlay_ctl.headers[0] = 0; 
                for (size_t i = 0; i < headers->size(); ++i) { 
                    strcat(mPlay_ctl.headers, headers->keyAt(i)); 
                    strcat(mPlay_ctl.headers, ": "); 
                    strcat(mPlay_ctl.headers, headers->valueAt(i)); 
                    strcat(mPlay_ctl.headers, "\r\n"); 
                } 
                mPlay_ctl.headers[len - 1] = '\0'; 
            } 
        } 
	} 
 
	mAmlogicFile.datasource=file; 
	mPlay_ctl.file_name=(char*)mAmlogicFile.datasource; 
	LOGV("setDataSource url=%s, len=%d\n", mPlay_ctl.file_name, strlen(mPlay_ctl.file_name)); 
	mState = STATE_OPEN; 
	return NO_ERROR; 
 
} 
 
 
 
 
status_t AmlogicPlayer::prepare() 
{ 
		LOGV("prepare\n"); 
		prepareAsync(); 
		while(player_get_state(mPlayer_id)!=PLAYER_INITOK) 
			{ 
			if((player_get_state(mPlayer_id))==PLAYER_ERROR || 
				player_get_state(mPlayer_id)==PLAYER_STOPED || 
				player_get_state(mPlayer_id)==PLAYER_PLAYEND) 
				{ 
				return UNKNOWN_ERROR; 
				} 
				usleep(1000*10); 
			} 
    	return NO_ERROR; 
} 
 
 
status_t AmlogicPlayer::prepareAsync() { 
	LOGV("prepareAsync\n"); 
	mPlay_ctl.callback_fn.update_statue_callback=updateprocess; 
	mPlay_ctl.callback_fn.update_interval=1000; 
	mPlay_ctl.need_start=1; 
	mPlay_ctl.audio_index=-1; 
	mPlay_ctl.video_index=-1; 
	mPlay_ctl.auto_buffing_enable=1; 
	mPlay_ctl.buffing_min=0.001; 
	mPlay_ctl.buffing_middle=0.04; 
	mPlay_ctl.buffing_max=0.8; 
	mPlay_ctl.enable_rw_on_pause=1; 
	mPlay_ctl.nosound=PropIsEnable("media.amplayer.noaudio")?1:0; 
	mPlay_ctl.novideo=PropIsEnable("media.amplayer.novideo")?1:0; 
	mPlayer_id=player_start(&mPlay_ctl,(unsigned long)this); 
	if(mPlayer_id>=0) 
		{ 
			LOGV("Start player,pid=%d\n",mPlayer_id); 
			return NO_ERROR; 
		} 
	return UNKNOWN_ERROR; 
} 
 
status_t AmlogicPlayer::start() 
{ 
    LOGV("start\n"); 
    if (mState != STATE_OPEN) { 
        return ERROR_NOT_OPEN; 
    } 
 
	player_start_play(mPlayer_id); 
 
	if(mPaused) 
		{ 
		player_resume(mPlayer_id); 
		} 
	VideoViewOn(); 
    mPaused = false; 
    mRender = true; 
	//sendEvent(MEDIA_PLAYER_STARTED); 
    // wake up render thread 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::stop() 
{ 
    LOGV("stop\n"); 
    if (mState != STATE_OPEN) { 
        return ERROR_NOT_OPEN; 
    } 
    mPaused = true; 
    mRender = false; 
	player_stop(mPlayer_id); 
	sendEvent(MEDIA_PLAYBACK_COMPLETE); 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::seekTo(int position) 
{ 
	if(position<0) 
	{/*cancel seek*/ 
		return NO_ERROR; 
	} 
	int time=position/1000; 
	LOGV("seekTo:%d\n",position); 
	player_timesearch(mPlayer_id,time); 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::pause() 
{ 
    LOGV("pause\n"); 
    if (mState != STATE_OPEN) { 
        return ERROR_NOT_OPEN; 
    } 
	if(mhasVideo) 
		player_pause(mPlayer_id); 
	else 
		{ 
		mIgnoreMsg=true; 
		mPlay_ctl.t_pos=mPlayTime/1000; 
		player_stop(mPlayer_id); 
		prepare(); 
		mIgnoreMsg=false; 
		} 
    mPaused = true; 
    return NO_ERROR; 
} 
 
bool AmlogicPlayer::isPlaying() 
{ 
    	///LOGV("isPlaying?----%d\n",mRender); 
	if(!mPaused) 
		return mRender; 
	else 
		return false; 
} 
status_t AmlogicPlayer::updateMediaInfo(void) 
{ 
	media_info_t minfo; 
	int ret; 
	if(mPlayer_id<0) 
		return OK; 
	ret=player_get_media_info(mPlayer_id,&minfo); 
	if(ret!=0) 
	{ 
		LOGV("player_get_media_info failed\n"); 
		return NO_INIT; 
	} 
	if(  minfo.stream_info.total_video_num>0 &&  
		 minfo.stream_info.cur_video_index>=0 && 
		 minfo.video_info[minfo.stream_info.cur_video_index]!=NULL) 
	{ 
			mWidth=minfo.video_info[minfo.stream_info.cur_video_index]->width; 
			mHeight=minfo.video_info[minfo.stream_info.cur_video_index]->height; 
			    
	} 
	mhasVideo=minfo.stream_info.has_video; 
	mhasAudio=minfo.stream_info.has_audio; 
	return OK; 
} 
 
 
status_t AmlogicPlayer::getMetadata( 
        const media::Metadata::Filter& ids, Parcel *records) { 
    using media::Metadata; 
	LOGV("getMetadata\n"); 
    Metadata metadata(records); 
 
    metadata.appendBool( 
            Metadata::kPauseAvailable,true); 
    metadata.appendBool( 
            Metadata::kSeekBackwardAvailable,false); 
 
    metadata.appendBool( 
            Metadata::kSeekForwardAvailable,false); 
	updateMediaInfo(); 
	metadata.appendBool(Metadata::kVideoWidth,mWidth); 
	metadata.appendBool(Metadata::kVideoHeight,mHeight); 
			    
    return OK; 
} 
 
status_t AmlogicPlayer::setVideoSurface(const sp<ISurface>& surface) 
{ 
	LOGV("Set setVideoSurface11\n"); 
    Mutex::Autolock autoLock(mMutex); 
    mISurface = surface; 
    updateMediaInfo(); 
    if ((mISurface != NULL) && (mOverlay == NULL))  { 
        sp<OverlayRef> ref = mISurface->createOverlay( 
            mWidth, mHeight, OVERLAY_FORMAT_YCbCr_420_SP, 0); 
 
        if (ref.get() == NULL) { 
            LOGE("Unable to create the overlay!"); 
            return UNKNOWN_ERROR; 
        } 
 
        //mOverlay = new Overlay(ref); 
        //LOGV("Overlay created %p", mOverlay); 
    } 
 
	return OK;  
} 
status_t AmlogicPlayer::getCurrentPosition(int* position) 
{ 
	//LOGV("getCurrentPosition\n"); 
	Mutex::Autolock autoLock(mMutex); 
	*position=mPlayTime; 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::getDuration(int* duration) 
{ 
	Mutex::Autolock autoLock(mMutex); 
    LOGV("getDuration\n"); 
	*duration=mDuration; 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::release() 
{ 
    LOGV("release\n"); 
	player_stop(mPlayer_id); 
	player_exit(mPlayer_id); 
	VideoViewClose(); 
	mPlayer_id=-1; 
	if(mAmlogicFile.datasource!=NULL) 
		free(mAmlogicFile.datasource); 
	mAmlogicFile.datasource=NULL; 
	if(mAmlogicFile.mFile!=NULL) 
		fclose(mAmlogicFile.mFile); 
	mAmlogicFile.mFile=NULL; 
	sendEvent(MEDIA_PLAYBACK_COMPLETE); 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::reset() 
{ 
	Mutex::Autolock autoLock(mMutex); 
	 LOGV("reset\n"); 
	///player_stop(mPlayer_id); 
	mPaused = true; 
    mRender = false; 
    return NO_ERROR; 
} 
 
// always call with lock held 
status_t AmlogicPlayer::reset_nosync() 
{ 
	Mutex::Autolock autoLock(mMutex); 
	 LOGV("reset_nosync\n"); 
    // close file 
    //player_stop_async(mPlayer_id); 
    return NO_ERROR; 
} 
 
status_t AmlogicPlayer::setLooping(int loop) 
{ 
	Mutex::Autolock autoLock(mMutex); 
    LOGV("setLooping\n"); 
    mLoop = (loop != 0); 
	if(mLoop) 
		player_loop(mPlayer_id); 
	else 
		player_noloop(mPlayer_id); 
    return NO_ERROR; 
} 
 
 
 
 
} // end namespace android