2 * gstvaapidecoder_dpb.c - Decoded Picture Buffer
4 * Copyright (C) 2012 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 #include "gstvaapidecoder_dpb.h"
26 #include "gstvaapidebug.h"
28 /* ------------------------------------------------------------------------- */
29 /* --- Common Decoded Picture Buffer utilities --- */
30 /* ------------------------------------------------------------------------- */
33 dpb_new(GType type, guint max_pictures)
38 g_return_val_if_fail(max_pictures > 0, NULL);
40 obj = gst_mini_object_new(type);
44 dpb = GST_VAAPI_DPB_CAST(obj);
45 dpb->pictures = g_new0(GstVaapiPicture *, max_pictures);
48 dpb->max_pictures = max_pictures;
52 gst_mini_object_unref(obj);
57 dpb_get_oldest(GstVaapiDpb *dpb, gboolean output)
59 gint i, lowest_pts_index;
61 for (i = 0; i < dpb->num_pictures; i++) {
62 if ((GST_VAAPI_PICTURE_IS_OUTPUT(dpb->pictures[i]) ^ output) == 0)
65 if (i == dpb->num_pictures)
68 lowest_pts_index = i++;
69 for (; i < dpb->num_pictures; i++) {
70 GstVaapiPicture * const picture = dpb->pictures[i];
71 if ((GST_VAAPI_PICTURE_IS_OUTPUT(picture) ^ output) != 0)
73 if (picture->poc < dpb->pictures[lowest_pts_index]->poc)
76 return lowest_pts_index;
80 dpb_remove_index(GstVaapiDpb *dpb, guint index)
82 GstVaapiPicture ** const pictures = dpb->pictures;
83 guint num_pictures = --dpb->num_pictures;
85 if (index != num_pictures)
86 gst_vaapi_picture_replace(&pictures[index], pictures[num_pictures]);
87 gst_vaapi_picture_replace(&pictures[num_pictures], NULL);
90 static inline gboolean
91 dpb_output(GstVaapiDpb *dpb, GstVaapiPicture *picture)
93 return gst_vaapi_picture_output(picture);
97 dpb_bump(GstVaapiDpb *dpb)
102 index = dpb_get_oldest(dpb, FALSE);
106 success = dpb_output(dpb, dpb->pictures[index]);
107 if (!GST_VAAPI_PICTURE_IS_REFERENCE(dpb->pictures[index]))
108 dpb_remove_index(dpb, index);
113 dpb_clear(GstVaapiDpb *dpb)
117 for (i = 0; i < dpb->num_pictures; i++)
118 gst_vaapi_picture_replace(&dpb->pictures[i], NULL);
119 dpb->num_pictures = 0;
122 /* ------------------------------------------------------------------------- */
123 /* --- Base Decoded Picture Buffer --- */
124 /* ------------------------------------------------------------------------- */
126 G_DEFINE_TYPE(GstVaapiDpb, gst_vaapi_dpb, GST_TYPE_MINI_OBJECT)
129 gst_vaapi_dpb_base_flush(GstVaapiDpb *dpb)
131 while (dpb_bump(dpb))
137 gst_vaapi_dpb_base_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
141 // Remove all unused pictures
143 while (i < dpb->num_pictures) {
144 GstVaapiPicture * const picture = dpb->pictures[i];
145 if (GST_VAAPI_PICTURE_IS_OUTPUT(picture) &&
146 !GST_VAAPI_PICTURE_IS_REFERENCE(picture))
147 dpb_remove_index(dpb, i);
152 // Store reference decoded picture into the DPB
153 if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
154 while (dpb->num_pictures == dpb->max_pictures) {
160 // Store non-reference decoded picture into the DPB
162 if (GST_VAAPI_PICTURE_IS_SKIPPED(picture))
164 while (dpb->num_pictures == dpb->max_pictures) {
165 for (i = 0; i < dpb->num_pictures; i++) {
166 if (!GST_VAAPI_PICTURE_IS_OUTPUT(picture) &&
167 dpb->pictures[i]->poc < picture->poc)
170 if (i == dpb->num_pictures)
171 return dpb_output(dpb, picture);
176 gst_vaapi_picture_replace(&dpb->pictures[dpb->num_pictures++], picture);
181 gst_vaapi_dpb_finalize(GstMiniObject *object)
183 GstVaapiDpb * const dpb = GST_VAAPI_DPB_CAST(object);
184 GstMiniObjectClass *parent_class;
188 g_free(dpb->pictures);
191 parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_dpb_parent_class);
192 if (parent_class->finalize)
193 parent_class->finalize(object);
197 gst_vaapi_dpb_init(GstVaapiDpb *dpb)
199 dpb->pictures = NULL;
200 dpb->num_pictures = 0;
201 dpb->max_pictures = 0;
205 gst_vaapi_dpb_class_init(GstVaapiDpbClass *klass)
207 GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
209 object_class->finalize = gst_vaapi_dpb_finalize;
210 klass->flush = gst_vaapi_dpb_base_flush;
211 klass->add = gst_vaapi_dpb_base_add;
215 gst_vaapi_dpb_flush(GstVaapiDpb *dpb)
217 GstVaapiDpbClass *klass;
219 g_return_if_fail(GST_VAAPI_IS_DPB(dpb));
221 klass = GST_VAAPI_DPB_GET_CLASS(dpb);
222 if (G_UNLIKELY(!klass || !klass->add))
228 gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
230 GstVaapiDpbClass *klass;
232 g_return_val_if_fail(GST_VAAPI_IS_DPB(dpb), FALSE);
233 g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
235 klass = GST_VAAPI_DPB_GET_CLASS(dpb);
236 if (G_UNLIKELY(!klass || !klass->add))
238 return klass->add(dpb, picture);
242 gst_vaapi_dpb_size(GstVaapiDpb *dpb)
244 g_return_val_if_fail(GST_VAAPI_IS_DPB(dpb), 0);
246 return dpb->num_pictures;
249 /* ------------------------------------------------------------------------- */
250 /* --- MPEG-2 Decoded Picture Buffer --- */
251 /* ------------------------------------------------------------------------- */
253 /* At most two reference pictures for MPEG-2 */
254 #define MAX_MPEG2_REFERENCES 2
256 G_DEFINE_TYPE(GstVaapiDpbMpeg2, gst_vaapi_dpb_mpeg2, GST_VAAPI_TYPE_DPB)
259 gst_vaapi_dpb_mpeg2_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
261 GstVaapiPicture *ref_picture;
264 g_return_val_if_fail(GST_VAAPI_IS_DPB_MPEG2(dpb), FALSE);
267 * Purpose: only store reference decoded pictures into the DPB
270 * - non-reference decoded pictures are output immediately
271 * - ... thus causing older reference pictures to be output, if not already
272 * - the oldest reference picture is replaced with the new reference picture
274 if (G_LIKELY(dpb->num_pictures == MAX_MPEG2_REFERENCES)) {
275 index = (dpb->pictures[0]->poc > dpb->pictures[1]->poc);
276 ref_picture = dpb->pictures[index];
277 if (!GST_VAAPI_PICTURE_IS_OUTPUT(ref_picture)) {
278 if (!dpb_output(dpb, ref_picture))
283 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
284 return dpb_output(dpb, picture);
287 index = dpb->num_pictures++;
288 gst_vaapi_picture_replace(&dpb->pictures[index], picture);
293 gst_vaapi_dpb_mpeg2_init(GstVaapiDpbMpeg2 *dpb)
298 gst_vaapi_dpb_mpeg2_class_init(GstVaapiDpbMpeg2Class *klass)
300 GstVaapiDpbClass * const dpb_class = GST_VAAPI_DPB_CLASS(klass);
302 dpb_class->add = gst_vaapi_dpb_mpeg2_add;
306 gst_vaapi_dpb_mpeg2_new(void)
308 return dpb_new(GST_VAAPI_TYPE_DPB_MPEG2, MAX_MPEG2_REFERENCES);
312 gst_vaapi_dpb_mpeg2_get_references(
314 GstVaapiPicture *picture,
315 GstVaapiPicture **prev_picture_ptr,
316 GstVaapiPicture **next_picture_ptr
319 GstVaapiPicture *ref_picture, *ref_pictures[MAX_MPEG2_REFERENCES];
320 GstVaapiPicture **picture_ptr;
323 g_return_if_fail(GST_VAAPI_IS_DPB_MPEG2(dpb));
324 g_return_if_fail(GST_VAAPI_IS_PICTURE(picture));
326 ref_pictures[0] = NULL;
327 ref_pictures[1] = NULL;
328 for (i = 0; i < dpb->num_pictures; i++) {
329 ref_picture = dpb->pictures[i];
330 index = ref_picture->poc > picture->poc;
331 picture_ptr = &ref_pictures[index];
332 if (!*picture_ptr || ((*picture_ptr)->poc > ref_picture->poc) == index)
333 *picture_ptr = ref_picture;
336 if (prev_picture_ptr)
337 *prev_picture_ptr = ref_pictures[0];
338 if (next_picture_ptr)
339 *next_picture_ptr = ref_pictures[1];