-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdpb.cc
296 lines (224 loc) · 7.76 KB
/
dpb.cc
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
* H.265 video codec.
* Copyright (c) 2013-2014 struktur AG, Dirk Farin <[email protected]>
*
* This file is part of libde265.
*
* libde265 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libde265 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libde265. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dpb.h"
#include "decctx.h"
#include <string.h>
#include <assert.h>
#define DPB_DEFAULT_MAX_IMAGES 30
decoded_picture_buffer::decoded_picture_buffer()
{
max_images_in_DPB = DPB_DEFAULT_MAX_IMAGES;
norm_images_in_DPB = DPB_DEFAULT_MAX_IMAGES;
}
decoded_picture_buffer::~decoded_picture_buffer()
{
for (int i=0;i<dpb.size();i++)
delete dpb[i];
}
void decoded_picture_buffer::log_dpb_content() const
{
for (int i=0;i<dpb.size();i++) {
loginfo(LogHighlevel, " DPB %d: POC=%d, ID=%d %s %s\n", i,
dpb[i]->PicOrderCntVal,
dpb[i]->get_ID(),
dpb[i]->PicState == UnusedForReference ? "unused" :
dpb[i]->PicState == UsedForShortTermReference ? "short-term" : "long-term",
dpb[i]->PicOutputFlag ? "output" : "---");
}
}
bool decoded_picture_buffer::has_free_dpb_picture(bool high_priority) const
{
// we will always adapt the buffer to insert high-priority images
if (high_priority) return true;
// quick test to check for free slots
if (dpb.size() < max_images_in_DPB) return true;
// scan for empty slots
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->PicOutputFlag==false && dpb[i]->PicState == UnusedForReference) {
return true;
}
}
return false;
}
int decoded_picture_buffer::DPB_index_of_picture_with_POC(int poc, int currentID, bool preferLongTerm) const
{
logdebug(LogHeaders,"DPB_index_of_picture_with_POC POC=%d\n",poc);
//log_dpb_content(ctx);
//loginfo(LogDPB,"searching for short-term reference POC=%d\n",poc);
if (preferLongTerm) {
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->PicOrderCntVal == poc &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState == UsedForLongTermReference) {
return k;
}
}
}
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->PicOrderCntVal == poc &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState != UnusedForReference) {
return k;
}
}
return -1;
}
int decoded_picture_buffer::DPB_index_of_picture_with_LSB(int lsb, int currentID, bool preferLongTerm) const
{
logdebug(LogHeaders,"get access to picture with LSB %d from DPB\n",lsb);
if (preferLongTerm) {
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->picture_order_cnt_lsb == lsb &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState == UsedForLongTermReference) {
return k;
}
}
}
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->picture_order_cnt_lsb == lsb &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState != UnusedForReference) {
return k;
}
}
return -1;
}
int decoded_picture_buffer::DPB_index_of_picture_with_ID(int id) const
{
logdebug(LogHeaders,"get access to picture with ID %d from DPB\n",id);
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->get_ID() == id) {
return k;
}
}
return -1;
}
void decoded_picture_buffer::output_next_picture_in_reorder_buffer()
{
assert(!reorder_output_queue.empty());
// search for picture in reorder buffer with minimum POC
int minPOC = reorder_output_queue[0]->PicOrderCntVal;
int minIdx = 0;
for (int i=1;i<reorder_output_queue.size();i++)
{
if (reorder_output_queue[i]->PicOrderCntVal < minPOC) {
minPOC = reorder_output_queue[i]->PicOrderCntVal;
minIdx = i;
}
}
// put image into output queue
image_output_queue.push_back(reorder_output_queue[minIdx]);
// remove image from reorder buffer
reorder_output_queue[minIdx] = reorder_output_queue.back();
reorder_output_queue.pop_back();
}
bool decoded_picture_buffer::flush_reorder_buffer()
{
// return 'false' when there are no pictures in reorder buffer
if (reorder_output_queue.empty()) return false;
while (!reorder_output_queue.empty()) {
output_next_picture_in_reorder_buffer();
}
return true;
}
void decoded_picture_buffer::clear()
{
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->PicOutputFlag ||
dpb[i]->PicState != UnusedForReference)
{
dpb[i]->PicOutputFlag = false;
dpb[i]->PicState = UnusedForReference;
dpb[i]->release();
}
}
reorder_output_queue.clear();
image_output_queue.clear();
}
int decoded_picture_buffer::new_image(std::shared_ptr<const seq_parameter_set> sps,
decoder_context* decctx,
de265_PTS pts, void* user_data, bool isOutputImage)
{
loginfo(LogHeaders,"DPB::new_image\n");
log_dpb_content();
// --- search for a free slot in the DPB ---
int free_image_buffer_idx = -1;
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->can_be_released()) {
dpb[i]->release(); /* TODO: this is surely not the best place to free the image, but
we have to do it here because releasing it in de265_release_image()
would break the API compatibility. */
free_image_buffer_idx = i;
break;
}
}
// Try to free a buffer at the end if the DPB got too large.
/* This should also probably move to a better place as soon as the API allows for this. */
if (dpb.size() > norm_images_in_DPB && // buffer too large
free_image_buffer_idx != dpb.size()-1 && // last slot not reused in this alloc
dpb.back()->can_be_released()) // last slot is free
{
delete dpb.back();
dpb.pop_back();
}
// create a new image slot if no empty slot remaining
if (free_image_buffer_idx == -1) {
free_image_buffer_idx = dpb.size();
dpb.push_back(new de265_image);
}
// --- allocate new image ---
de265_image* img = dpb[free_image_buffer_idx];
int w = sps->pic_width_in_luma_samples;
int h = sps->pic_height_in_luma_samples;
enum de265_chroma chroma;
switch (sps->chroma_format_idc) {
case 0: chroma = de265_chroma_mono; break;
case 1: chroma = de265_chroma_420; break;
case 2: chroma = de265_chroma_422; break;
case 3: chroma = de265_chroma_444; break;
default: chroma = de265_chroma_420; assert(0); break; // should never happen
}
img->alloc_image(w,h, chroma, sps, true, decctx, /*NULL,*/ pts, user_data, isOutputImage);
img->integrity = INTEGRITY_CORRECT;
return free_image_buffer_idx;
}
void decoded_picture_buffer::pop_next_picture_in_output_queue()
{
image_output_queue.pop_front();
loginfo(LogDPB, "DPB output queue: ");
for (int i=0;i<image_output_queue.size();i++) {
loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
}
void decoded_picture_buffer::log_dpb_queues() const
{
loginfo(LogDPB, "DPB reorder queue (after push): ");
for (int i=0;i<num_pictures_in_reorder_buffer();i++) {
loginfo(LogDPB, "*%d ", reorder_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
loginfo(LogDPB, "DPB output queue (after push): ");
for (int i=0;i<num_pictures_in_output_queue();i++) {
loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
}