-
Notifications
You must be signed in to change notification settings - Fork 3
/
frame.c
144 lines (126 loc) · 3.91 KB
/
frame.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "frame.h"
#include "player.h"
void frame_queue_unref_item(frame_t *vp)
{
av_frame_unref(vp->frame);
}
int frame_queue_init(frame_queue_t *f, packet_queue_t *pktq, int max_size, int keep_last)
{
int i;
memset(f, 0, sizeof(frame_queue_t));
if (!(f->mutex = SDL_CreateMutex())) {
av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError());
return AVERROR(ENOMEM);
}
if (!(f->cond = SDL_CreateCond())) {
av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
return AVERROR(ENOMEM);
}
f->pktq = pktq;
f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE);
f->keep_last = !!keep_last;
for (i = 0; i < f->max_size; i++)
if (!(f->queue[i].frame = av_frame_alloc()))
return AVERROR(ENOMEM);
return 0;
}
void frame_queue_destory(frame_queue_t *f)
{
int i;
for (i = 0; i < f->max_size; i++) {
frame_t *vp = &f->queue[i];
frame_queue_unref_item(vp);
av_frame_free(&vp->frame);
}
SDL_DestroyMutex(f->mutex);
SDL_DestroyCond(f->cond);
}
void frame_queue_signal(frame_queue_t *f)
{
SDL_LockMutex(f->mutex);
SDL_CondSignal(f->cond);
SDL_UnlockMutex(f->mutex);
}
frame_t *frame_queue_peek(frame_queue_t *f)
{
return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
}
frame_t *frame_queue_peek_next(frame_queue_t *f)
{
return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size];
}
// 取出此帧进行播放,只读取不删除,不删除是因为此帧需要缓存下来供下一次使用。播放后,此帧变为上一帧
frame_t *frame_queue_peek_last(frame_queue_t *f)
{
return &f->queue[f->rindex];
}
// 向队列尾部申请一个可写的帧空间,若无空间可写,则等待
frame_t *frame_queue_peek_writable(frame_queue_t *f)
{
/* wait until we have space to put a new frame */
SDL_LockMutex(f->mutex);
int signaled = 1;
while (signaled && f->size >= f->max_size &&
!f->pktq->abort_request) {
signaled = SDL_CondWaitTimeout(f->cond, f->mutex, 20);
}
SDL_UnlockMutex(f->mutex);
if (f->pktq->abort_request)
return NULL;
return &f->queue[f->windex];
}
// 从队列头部读取一帧,只读取不删除,若无帧可读则等待
frame_t *frame_queue_peek_readable(frame_queue_t *f)
{
int signaled = 1;
/* wait until we have a readable a new frame */
SDL_LockMutex(f->mutex);
while (signaled && f->size - f->rindex_shown <= 0 &&
!f->pktq->abort_request) {
signaled = SDL_CondWaitTimeout(f->cond, f->mutex, 20);
}
SDL_UnlockMutex(f->mutex);
if (f->pktq->abort_request)
return NULL;
return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
}
// 向队列尾部压入一帧,只更新计数与写指针,因此调用此函数前应将帧数据写入队列相应位置
void frame_queue_push(frame_queue_t *f)
{
if (++f->windex == f->max_size)
f->windex = 0;
SDL_LockMutex(f->mutex);
f->size++;
SDL_CondSignal(f->cond);
SDL_UnlockMutex(f->mutex);
}
// 读指针(rindex)指向的帧已显示,删除此帧,注意不读取直接删除。读指针加1
void frame_queue_next(frame_queue_t *f)
{
if (f->keep_last && !f->rindex_shown) {
f->rindex_shown = 1;
return;
}
frame_queue_unref_item(&f->queue[f->rindex]);
if (++f->rindex == f->max_size)
f->rindex = 0;
SDL_LockMutex(f->mutex);
f->size--;
SDL_CondSignal(f->cond);
SDL_UnlockMutex(f->mutex);
}
// frame_queue中未显示的帧数
/* return the number of undisplayed frames in the queue */
int frame_queue_nb_remaining(frame_queue_t *f)
{
return f->size - f->rindex_shown;
}
/* return last shown position */
int64_t frame_queue_last_pos(frame_queue_t *f)
{
frame_t *fp = &f->queue[f->rindex];
if (f->rindex_shown && fp->serial == f->pktq->serial)
return fp->pos;
else
return -1;
}