#include "packet.h" int packet_queue_init(packet_queue_t *q, CMediaHostApi* hostapi) { memset(q, 0, sizeof(packet_queue_t)); q->mutex = SDL_CreateMutex(); if (!q->mutex){ hostapi->Debug(MEDIA_LOG_DEBUG, "SDL_CreateMutex(): %s.", SDL_GetError()); return AVERROR(ENOMEM); } q->packet_cond = SDL_CreateCond(); if (!q->packet_cond){ hostapi->Debug(MEDIA_LOG_DEBUG, "SDL_CreateCond(): %s.", SDL_GetError()); return AVERROR(ENOMEM); } q->abort_flag = 0; return 0; } // 写队列尾部。pkt是一包还未解码的音频数据 int packet_queue_put(packet_queue_t *q, AVPacket *pkt, CMediaHostApi* hostapi) { AVPacketList* pkt_list = NULL; if (av_packet_make_refcounted(pkt) < 0){ hostapi->Debug(MEDIA_LOG_DEBUG, "[pkt] is not refrence counted."); return -1; } pkt_list = (AVPacketList*)av_malloc(sizeof(AVPacketList)); if (!pkt_list){ return -1; } pkt_list->pkt = *pkt; pkt_list->next = NULL; SDL_LockMutex(q->mutex); // 队列为空 if (!q->last_pkt){ q->first_pkt = pkt_list; } else{ q->last_pkt->next = pkt_list; } q->last_pkt = pkt_list; q->nb_packets++; q->packet_queue_size += pkt_list->pkt.size; //hostapi->Debug(MEDIA_LOG_DEBUG, "[%p] packet_queue_put current packet queue len is %d.", q, q->nb_packets); // 发个条件变量的信号:重启等待q->cond条件变量的一个线程 SDL_CondSignal(q->packet_cond); SDL_UnlockMutex(q->mutex); return 0; } // 读队列头部。 int packet_queue_get(packet_queue_t *q, AVPacket *pkt, int block, CMediaHostApi* hostapi) { AVPacketList *p_pkt_node = NULL; int ret = -1; SDL_LockMutex(q->mutex); while (0 == q->abort_flag) { p_pkt_node = q->first_pkt; if (p_pkt_node) // 队列非空,取一个出来 { q->first_pkt = p_pkt_node->next; if (!q->first_pkt) { q->last_pkt = NULL; } q->nb_packets--; //hostapi->Debug(MEDIA_LOG_DEBUG, "[%p] packet_queue_get current packet queue len is %d.", q, q->nb_packets); q->packet_queue_size -= p_pkt_node->pkt.size; *pkt = p_pkt_node->pkt; av_free(p_pkt_node); ret = 1; break; } else if (!block) // 队列空且阻塞标志无效,则立即退出 { ret = 0; break; } else // 队列空且阻塞标志有效,则等待 { if (SDL_MUTEX_TIMEDOUT == SDL_CondWaitTimeout(q->packet_cond, q->mutex, 1000)){ break; } } } SDL_UnlockMutex(q->mutex); return ret; } int packet_queue_put_nullpacket(packet_queue_t *q, int stream_index, CMediaHostApi* hostapi) { AVPacket pkt1, *pkt = &pkt1; av_init_packet(pkt); pkt->data = NULL; pkt->size = 0; pkt->stream_index = stream_index; return packet_queue_put(q, pkt, hostapi); } void packet_queue_flush(packet_queue_t *q) { AVPacketList *pkt, *pkt1; SDL_LockMutex(q->mutex); for (pkt = q->first_pkt; pkt; pkt = pkt1) { pkt1 = pkt->next; if (pkt->pkt.size > 0) { q->packet_queue_size -= pkt->pkt.size; av_packet_unref(&pkt->pkt); av_freep(&pkt); q->nb_packets--; } } q->last_pkt = NULL; q->first_pkt = NULL; q->nb_packets = 0; q->packet_queue_size = 0; q->duration = 0; SDL_UnlockMutex(q->mutex); } void packet_queue_destroy(packet_queue_t *q, CMediaHostApi* m_hostapi) { packet_queue_flush(q); SDL_DestroyMutex(q->mutex); SDL_DestroyCond(q->packet_cond); m_hostapi->Debug(MEDIA_LOG_DEBUG, "packet queue destroy."); } void packet_queue_abort(packet_queue_t *q, CMediaHostApi* m_hostapi) { SDL_LockMutex(q->mutex); q->abort_flag = 1; m_hostapi->Debug(MEDIA_LOG_DEBUG, "packet_queue_abort, CondSignal cond."); SDL_CondSignal(q->packet_cond); SDL_UnlockMutex(q->mutex); }