当前位置:   article > 正文

ijkplayer系列4:消息队列MessageQueue_android jkplayer

android jkplayer

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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清零。
  • 1
  • 2
  • 3
  • 4
  • 5

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) 
清空队列。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

创建和销毁队列的正确姿势如下:

 // 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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/956933
推荐阅读
相关标签
  

闽ICP备14008679号