赞
踩
jkplayer中传递消息一般采用的是生产者-消费者模式。大致原理如下:
生产者可以位于任何一个线程向队列中添加消息,而消费者(通常只有一个)则通过一个独立的线程不断地从队列中获取消息,当没有消息时阻塞(也可以配置成不阻塞,但通常我们会阻塞),当队列中止使用时线程退出。队列何时中止一般由生产者决定。显然,这种模式的核心就是这个消息队列。
ijkplayer的消息队列命名为MessageQueue,不论是从名称还是结构体的字段定义,你都可以从中看到Android的影子,所以ijkplayer的MessageQueue应该是仿照Android中消息队列的设计。
MessageQueue声明和实现都位于ff_ffmsg_queue.h中,关联的结构体有以下两个:
typedef struct AVMessage { // 参考Android Message#what int what; // 参考Android Message#arg1 int arg1; // 参考Android Message#arg2 int arg2; // 参考Android Message#obj void *obj; // 释放obj,仅当使用msg_queue_put_simple4来添加消息时不为NULL void (*free_l)(void *obj); // 指向下一个消息 struct AVMessage *next; } AVMessage; typedef struct MessageQueue { AVMessage *first_msg, *last_msg; int nb_messages; int abort_request; SDL_mutex *mutex; SDL_cond *cond; AVMessage *recycle_msg; int recycle_count; int alloc_count; } MessageQueue;
AVMessage存储消息内容,并且可以指向下一条消息,而MessageQueue即为消息队列。我们不需要关心MessageQueue的成员信息,因为不会直接使用到,我们对MessageQueue的所有操作都是通过函数来达成,
而AVMessage的成员则可能会直接使用到。
下面我们来看下MessageQueue和AVMessage都提供了哪些函数来操作它们。首先来看下AVMessage相关的函数:
void msg_free_res(AVMessage *msg)
释放msg的obj成员内存,并将obj置为NULL。注意,不是释放msg本身。
void msg_init_msg(AVMessage *msg)
初始化msg,其实就是调用memset清零。
AVMessage相关的函数就只有上面两个了,好像可有可无的样子,下面我们来看下MessageQueue的相关函数:
void msg_queue_init(MessageQueue *q) 初始化MessageQueue,这里面是有实实在在做事情的,所以创建完MessageQueue后不要忘了调用此方法进行初始化工作。 void msg_queue_start(MessageQueue *q) 启用MessageQueue,初始化完成后还不能使用MessageQueue,必须在调用此方法后才可以进行后续操作。同时触发FFP_MSG_FLUSH事件。 void msg_queue_abort(MessageQueue *q) 中止MessageQueue的使用,可以再次调用msg_queue_start()来重新启用MessageQueue。 void msg_queue_destroy(MessageQueue *q) 销毁MessageQueue,释放成员内存,可以再次调用msg_queue_init()来重新初始化。注意,不会释放MessageQueue本身。 int msg_queue_put(MessageQueue *q, AVMessage *msg) 添加消息,MessageQueue abort时返回-1,正常返回>=0的数。 void msg_queue_put_simple1(MessageQueue *q, int what); void msg_queue_put_simple2(MessageQueue *q, int what, int arg1); void msg_queue_put_simple3(MessageQueue *q, int what, int arg1, int arg2); void msg_queue_put_simple4(MessageQueue *q, int what, int arg1, int arg2, void *obj, int obj_len); 添加消息,不同函数表示传入的参数的多寡。这里返回值居然是void而不是和msg_queue_put()相同的int类型,真令人费解。 int msg_queue_get(MessageQueue *q, AVMessage *msg, int block) 获取队首消息,同时将该消息从队列中移除。block不为0时表示阻塞模式,为0表示非阻塞模式,阻塞模式下如果当前队列中没有消息,则会阻塞直到有新的消息加入才返回该消息,否则直接返回0。MessageQueue abort时返回-1,正常返回>=0的数。 void msg_queue_remove(MessageQueue *q, int what) 移除指定what的所有消息。 void msg_queue_flush(MessageQueue *q) 清空队列。
创建和销毁队列的正确姿势如下:
// create
MessageQueue* q = (MessageQueue*)malloc(sizeof(MessageQueue);
msg_queue_init(q);
msg_queue_start(q);
// destroy
msg_queue_abort(q);
msg_queue_destroy(q);
free(q);
q = NULL;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。