ijkplayer系列4:消息队列MessageQueue

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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值