关于文件播放时程序抛出异常

bll218 2009-04-22 03:44:37
下面是通过调用BREW的多媒体播放接口实现播放音乐文件的程序,第一个函数是播放回调函数,该函数在第二个函数里进行注册。第二个函数是文件播放函数,第三个函数是停止播放函数。假设通过按数字键1 调用文件播放函数,通过数字键2 调用停止播放函数。
在正常情况下,可以对文件进行播放与停止操作,也没有出现错误。但在一种情况下会出现错误,就是,我快速的,不停的进行数字1和数字2两个键交替按下。简单的说就是不停的,快速的执行 播放--停止--播放 ,操作,就会抛出:“应用程序异常...”的错误。
我估计是问题是,按了数字1后,回调函数还没有来的及注册,我就按了2。因为我重复按这两个键的速度是很快的。
不知道是不是这种原因,请高手看下,希望能提出程序中的不足之处,最好是能指出出现上面的错误的原因。
补充一点,就是我是在模拟器上进行上面的操作的。在模拟器调试状态下,出现这中错误的情况比执行状态下少很多,或着说在调试状态下不容易出现我上面说的错误。
/*********************************************************************
//函数名: popmusic_playResult
//功能描述: 响应播放回调消息
//输入参数:
//1, puser: 主程序结构体
//2, pCmdNotify: 播放器消息参数
//输出参数:
// 无
//返回值:
// 无
*********************************************************************/
static void popmusic_playResult(void *puser, AEEMediaCmdNotify *pCmdNotify)
{
//int ire;
myfirstapp* pMe = (myfirstapp*)puser;

int iMini = 0;
int iSecend = 0;
int itotletime = 0;
int iseekmode = MM_SEEK_MODE_TIME;
int iCurrent = 0;
double Addincrement = 0.00;

//MEMSET(pMe->m_szCurrPre, 0, 16);
if (pCmdNotify->nCmd == MM_CMD_PLAY || pCmdNotify->nCmd == MM_CMD_RECORD) // IMEDIA_Play/IMEDIA_Record events
{
switch (pCmdNotify->nStatus)
{
case MM_STATUS_TICK_UPDATE:
{
iCurrent = 0;
Addincrement = (1000+97)/1000.00;
pMe->m_dwPlayprs += Addincrement;
}
break;
default:
break;
}
}
else if (pCmdNotify->nCmd == MM_CMD_GETTOTALTIME)
{
if (pCmdNotify->nStatus == MM_STATUS_DONE || pCmdNotify->nStatus == MM_STATUS_ABORT)
{
MEMSET((char *)pMe->m_szTotalTime, 0, 16);
pMe->m_dwPlayprs = 0;
itotletime = (uint16)(((uint32)pCmdNotify->pCmdData) / 1000 );
pMe->m_dwTotalTime = itotletime;
IMEDIA_Play(pMe->m_pMedia); //播放文件

}
}
else if (pCmdNotify->nCmd == MM_CMD_SETMEDIAPARM)
{
if (pCmdNotify->nSubCmd == MM_PARM_VOLUME && pCmdNotify->nStatus == MM_STATUS_DONE)
{
IMEDIA_GetMediaParm(pMe->m_pMedia, MM_PARM_VOLUME, NULL, NULL);
return;
}
}
else if (pCmdNotify->nCmd == MM_CMD_GETMEDIAPARM) // IMEDIA_GetMediaParm() events
{
if (pCmdNotify->nSubCmd == MM_PARM_VOLUME && pCmdNotify->nStatus == MM_STATUS_DONE)
{
pMe->m_wVolume = (uint16)(uint32)pCmdNotify->pCmdData;
}
}
}
/*********************************************************************
//函数名: popmusic_play_file
//功能描述: 初始化IMedia接口对象,注册回调函数,以实现播放功能
//输入参数:
//1, pszFile: 歌曲全路径文件名
//2, player_handler: 播放消息回调函数
//输出参数:
// 无
//返回值:
// 无
*********************************************************************/
void popmusic_play_file(const char *pszFile, popmusic_play_notify_callback player_handler)
{
myfirstapp* pMe = pMfp;
int nRet;
char *filesz = STRDUP(pszFile);

pMe->m_md.clsData = MMD_FILE_NAME;
pMe->m_md.pData = (void *)filesz;
pMe->m_md.dwSize = 0;
pMe->szFileName = (char *)pszFile;
nRet = AEEMediaUtil_CreateMedia(pMe->pIShell, &pMe->m_md, &pMe->m_pMedia);
if(nRet == SUCCESS)
{
if(SUCCESS == IMEDIA_RegisterNotify(pMe->m_pMedia, player_handler, pMe))
{
IMEDIA_GetMediaParm(pMe->m_pMedia, MM_PARM_VOLUME, NULL, NULL);
IMEDIA_GetTotalTime(pMe->m_pMedia);
}
}
}
/*********************************************************************
//函数名: popmusic_player_stop
//功能描述: 停止播放
//输入参数:
// 无
//输出参数:
// 无
//返回值:
// 无
*********************************************************************/
void popmusic_player_stop()
{
myfirstapp* pMe = pMfp;
IMEDIA_Stop(pMe->m_pMedia);
}
...全文
1618 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
allen1986 2009-05-07
  • 打赏
  • 举报
回复
在调用STOP之后,BREW会去处理停止播放事件,在该事件处理完后,会给发送一个mm_status_done消息,在这个消息里面去取消回调,释放资源。然后做其他的事情,比如你想再播放,那就得将播放函数在mm_status_done里面调用。不然会出问题的。
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zsf81 的回复:]
俺说一遍流程和注意事项
register后,状态要notice返回,play之后,如果手动按停止,就必须调用STOP接口之后,在notice收到DONE的消息之后才能去释放REGISTER。或者也可以不做,直到APP结束,会自动释放。

如果不是手动停止,那就会有UPDATE消息,不用管,直到播放完成。会有DONE消息,这时就表示停止。
[/Quote]
已经说得很清楚了
bll218 2009-04-23
  • 打赏
  • 举报
回复
延时加在IMEDIA_RegisterNotify()函数之后,IMEDIA_GetTotalTime()函数之前可以吗?
bll218 2009-04-23
  • 打赏
  • 举报
回复
确实,在STOP中调用IMEDIA_RegisterNotify(pMe->m_popmgemode.m_pMedia, NULL, pMe);可以不再调用回调函数。
天生,我按照你说的只注册一次IMEDIA_RegisterNotify(),我是在 popmusic_play_file()中做了一个处理:
if(pme->flag==-1)
pme->flag = IMEDIA_RegisterNotify(pMe->m_popmgemode.m_pMedia, player_handler, pMe);
if(SUCCESS == pme->flag)
{
IMEDIA_GetMediaParm(pMe->m_popmgemode.m_pMedia, MM_PARM_VOLUME, NULL, NULL);
IMEDIA_GetTotalTime(pMe->m_popmgemode.m_pMedia);
}

flag的初值是-1,在初始化应用时设置的。

但这样处理了后,STOP之后在次调用这个popmusic_play_file()时,就播放不出音乐了。把STOP里面的
IMEDIA_RegisterNotify(pMe->m_popmgemode.m_pMedia, NULL, pMe);屏蔽掉,结果还是播放不成功。
不知道是不是我对“只注册一次”的理解是错的。
zsf81 2009-04-23
  • 打赏
  • 举报
回复
先STOP,再去IMEDIA_RegisterNotify(),把第二个参数写NULL
zsf81 2009-04-23
  • 打赏
  • 举报
回复
那你就再重新理清一下思路,再来做,你连自己想做啥都不清楚
bll218 2009-04-23
  • 打赏
  • 举报
回复
现在主要问题是,PLAY 函数是异步调用的,我是在MM_CMD_GETTOTALTIME里面调用PLAY的,当状态为MM_STATUS_DONE || MM_STATUS_ABORT时调用PLAY。我调用PLAY后快速的调用STOP,之后在次调用PLAY,发现pCmdNotify->pCmdData为0,状态是MM_STATUS_ABORT。接着程序就抛出异常。该怎样去做这个DELAY,我在调用STOP之前加上if(flag==TRUE),并且,让程序等待一段时间。 flag 又是在PLAY之后附值的。还是不能解决问题。
我还是刚刚接触BREW,有些地方还很不是很清楚。
sunyymq 2009-04-23
  • 打赏
  • 举报
回复
来学习一下!
zsf81 2009-04-23
  • 打赏
  • 举报
回复
俺说一遍流程和注意事项
register后,状态要notice返回,play之后,如果手动按停止,就必须调用STOP接口之后,在notice收到DONE的消息之后才能去释放REGISTER。或者也可以不做,直到APP结束,会自动释放。

如果不是手动停止,那就会有UPDATE消息,不用管,直到播放完成。会有DONE消息,这时就表示停止。
bll218 2009-04-22
  • 打赏
  • 举报
回复
我在调试时,执行了STOP后,发现函数popmusic_playResult()还在执行,里面的
case MM_STATUS_TICK_UPDATE:
中的语句还会被调用。
我想知道有没办法在STOP的时候将这个回调函数注销掉,不让它执行了。
不知道楼上说的只注册一回是不是只调用一次IMEDIA_RegisterNotify(),
我下次在点击播放时,不需要在执行这个函数了?
zsf81 2009-04-22
  • 打赏
  • 举报
回复
PLAY和STOP回调有个时差,这个是会出问题的,你可以做个DELAY。注册只需要做一回,而且没看到你的播和注册之前的关系。

2,851

社区成员

发帖
与我相关
我的任务
社区描述
本论坛以AI、WoS 、XR、IoT、Auto、生成式AI等核心板块组成,为开发者提供便捷及高效的学习和交流平台。 高通开发者专区主页:https://qualcomm.csdn.net/
人工智能物联网机器学习 技术论坛(原bbs) 北京·东城区
社区管理员
  • csdnsqst0050
  • chipseeker
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧