ffmplay---源码分析(一):自定义队列---PacketQueue

本文介绍了ffmpeg中的PacketQueue结构,包括创建、销毁、启用、终止使用、写入和读取AVPacket的过程。重点讨论了PacketQueue在处理线程间同步及数据共享时的细节,如block参数、flush_pkt的使用,以及数据存取的两种实现方式,并分析了数据缓存管理的重要性。
摘要由CSDN通过智能技术生成

PacketQueue

typedef struct PacketQueue {
   
    MyAVPacketList *first_pkt, *last_pkt;   //队首,队尾指针
    int nb_packets;  	//队列中一共有多少个节点
    int size;        	//队列所有节点字节总数,用于计算cache大小
    int64_t duration; 	//队列所有节点的合计时长
    int abort_request; 	//1终止  0正常运行
    int serial;        	队列序列号(=最后节点的serial,≥前面节点的serial)当插入flush_pkt时+1
    SDL_mutex *mutex;  	// 互斥信号量-----保证对队列的多线程安全(正确读写)👈因为有“主线程和callback函数”2个线程要访问
    SDL_cond *cond;    	// 条件变量----------保证线程的同步操作👈因为有“主线程和callback函数”2个线程要访问
} PacketQueue;

typedef struct MyAVPacketList {
   
    AVPacket pkt;
    struct MyAVPacketList *next;
    int serial;	//ffplay中多处用到serial的概念,一般用于区分是否连续数据
} MyAVPacketList;//单个节点

PacketQueue操作提供以下方法:

//serial用于识别是否属于连续的图像
packet_queue_init	初始化	//初始化用于初始各个字段的值,并创建mutex和cond:
packet_queue_destroy销毁//销毁过程负责清理mutex和cond.
packet_queue_start	启用
packet_queue_abort	中止
packet_queue_get	获取一个节点  = PacketQuene更新 + 拿出后free,没有且就阻塞等/非阻塞返回 
packet_queue_put	存入一个节点  = 写入packet_queue_put_private + 释放av_packet_unref
	真正放入:packet_queue_put_private = av_malloc + 填充 + 入队(链表) + PacketQuene更新
packet_queue_put_nullpacket:存入一个空节点
packet_queue_flush	清除队列内所有的节点

由于向队列的插入数据实在主线程中完成的,而取数据则是在callback线程中进行的,所以有可能在
取数据的时候,队列为空。在packet_queue_get中有一个block参数,指定在无数据的时候是否阻塞线程等待。

1、创建(设abort_request = 1)

static int packet_queue_init(PacketQueue *q)
{
   
    memset(q, 0, sizeof(PacketQueue));
    q->mutex = SDL_CreateMutex();
    //if (!q->mutex) {av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());return AVERROR(ENOMEM);}
    q->cond = SDL_CreateCond();
    //if (!q->cond) {av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());return AVERROR(ENOMEM);}
    q->abort_request = 1;//
    return 0;
}

2、销毁

static void packet_queue_destroy(PacketQueue *q)
{
   
    packet_queue_flush(q);
    SDL_DestroyMutex(q->mutex);
    SDL_DestroyCond(q->cond);
}

2.1 清空队列中的所有节点。比如用于销毁队列、seek操作等

static void packet_queue_flush(PacketQueue *q)		
{
   
    MyAVPacketList *pkt, *pkt1;SDL_LockMutex(q->mutex);
    for (pkt = q->first_pkt; pkt; pkt = pkt1) {
   
        pkt1 = pkt->next;
        av_packet_unref(&pkt->pkt);
        av_freep(&pkt);
    }
    q->last_pkt = NULL;
    q->first_pkt = NULL;
    q->nb_packets 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值