C代码线程锁结合工作Bookmark功能的实现
2019-01-02 本文已影响0人
Spirituality韬
- 需求如下:播放刻录文件时退出时要求保留offset,下次在播放时seek。客户需求很简单,但是领导要求拓展功能,防止中途突然断电的这种情况,要求播放过程中每隔30s保存bookmark。
接口已经封装这里只看一小部分,添加Bookmark代码
JT_StatusCode_t JTAPIBOOKMARK_AddBookMark(PST_JTAPIBOOKMARK_Data pstData)
{
#ifdef ANDROID_PLATFORM
JT_S8 path[128] = {0};
JT_S8 *tmp = strrchr(pstData->file, '/');
int size = tmp - pstData->file;
memcpy(path, pstData->file, size);
JTHDIVFS_ChangeCurrentDir(path);
#else
JTHDIVFS_ChangeCurrentDir("/");
#endif
JT_StatusCode_t status_code = JT_SUCCESS;
JT_U8 msg[128];
FILE * fd;
system("mv Bookmark.xml bookmark.xml");
fd = fopen("Bookmark.xml","a+");
fputs("<Bookmark>\n",fd);
memset(msg ,0 ,128);
sprintf(msg ,"<filename>%s</filename>\n",pstData->file);
fputs(msg ,fd);
memset(msg ,0 ,128);
sprintf(msg ,"<offset>%d</offset>\n", pstData->u64seekoffset);
fputs(msg ,fd);
fputs("</Bookmark>\n",fd);
if (fclose(fd) != 0)
{
status_code = JT_FAILED;
}
system("cat bookmark.xml >> Bookmark.xml");
system("rm -f bookmark.xml");
JTHDIVFS_ChangeCurrentDir("/");
return status_code;
}
代码很简单,因为之前都是在Linux平台上面使用,这里自己修改用Android 宏隔开,Bookmark.xml要求保存在同刻录文件目录下,BookMark结构体由filename(路径/文件名)和offset构成十分简单。
整体逻辑也很容易实现,在播放时查询有没有Bookmark,如果有,seek offset,然后删除Bookmark(防止有多个Bookmark),退出时,保存Bookmark。
现在就是拓展需求,要求每隔30s去添加Bookmark。开启个线程来做此操作,但是C代码来实现线程并没有什么经验,于是去网上查找的部分解决方案。
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static int flag = 0;
//static char cur_play_name[256];
void srpthread_init()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
}
void srpthread_suspend()
{
pthread_mutex_lock(&mutex);
flag--;
pthread_mutex_unlock(&mutex);
}
void srpthread_resume()
{
pthread_mutex_lock(&mutex);
flag++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
static void StartBookMark(void *args)
{
PST_JTAPIBOOKMARK_Data pstData;
JTAPIMedia_PlayStatusParams_t play_status ;
pstData = (PST_JTAPIBOOKMARK_Data)JTOS_MemMalloc(sizeof(ST_JTAPIBOOKMARK_Data));
while(1)
{
pthread_mutex_lock(&mutex);
while(flag<=0)
{
pthread_cond_wait(&cond,&mutex);
}
pthread_mutex_unlock(&mutex);
sleep(30);
....
}
}
StartBookMark是线程执行函数,利用锁来控制线程的执行,逻辑大致是播放开始时resume 释放锁,将会开始执行sleep之后的代码(添加Bookmark)然后循环,stop时调用suspend,然后在pthread_cond_wait(&cond,&mutex)处等待下一次的resume
感觉一切完美,没有什么毛病,自己也测试了一下功能OK吗,但是领导review一下代码,代码不够规范(什么可能编译不能通过,反正不太懂),要改用海思的接口来实现这个方案。
莫名其妙地自己又去看海思的接口,然后看看在接口在其他部分是怎么调用的,最后找嵌入式同事帮忙。
static JTOS_QueueId_t g_bookmark_queue = JT_INVALID_ID;
static JTOS_TaskId_t g_bookmark_task = JT_INVALID_ID;
static JTOS_MutexId_t bookmark_mutex_id = JT_INVALID_ID;
static int flag = 0;
#define mutex_Lock() \
do { \
if(JT_INVALID_ID == bookmark_mutex_id) \
{ \
(void)JTOS_MutexCreate(&bookmark_mutex_id); \
} \
\
if((JT_INVALID_ID == bookmark_mutex_id) || (JT_SUCCESS != JTOS_MutexLock(bookmark_mutex_id, JTOS_TIMEOUT_INFINITY))) \
{ \
JT_ERROR(("JTOS_MutexCreate or JTOS_MutexLock ird_mutex_id Failed\n")); \
} \
}while(0)
#define mutex_Unlock() \
do { \
if(JT_INVALID_ID == bookmark_mutex_id) \
{ \
(void)JTOS_MutexCreate(&bookmark_mutex_id); \
} \
\
if((JT_INVALID_ID == bookmark_mutex_id) || (JT_SUCCESS != JTOS_MutexUnlock(bookmark_mutex_id))) \
{ \
JT_ERROR(("JTOS_MutexCreate or JTOS_MutexUnlock ird_mutex_id Failed\n")); \
} \
}while(0)
void srpthread_suspend()
{
mutex_Lock();
flag--;
mutex_Unlock();
}
void srpthread_resume()
{
JT_U32 au32Msg[4] = {0};
mutex_Lock();
flag++;
JTOS_QueueSend(g_bookmark_queue, au32Msg, JTOS_TIMEOUT_IMMEDIATE);
mutex_Unlock();
}
static void StartBookMark(void *args)
{
JT_StatusCode_t enStatusCode = JT_SUCCESS;
JT_U32 au32Msg[4] = {0};
PST_JTAPIBOOKMARK_Data pstData;
JTAPIMedia_PlayStatusParams_t play_status ;
pstData = (PST_JTAPIBOOKMARK_Data)JTOS_MemMalloc(sizeof(ST_JTAPIBOOKMARK_Data));
while(1)
{
while(flag <= 0)
{
enStatusCode = JTOS_QueueReceive(g_bookmark_queue, au32Msg, JTOS_TIMEOUT_INFINITY);
}
...
}
}
逻辑和之前差不多只是,换用了海思的接口,利用Send 、Receive形式来使用等待操作