1 /*
2  *  gstvaapiencoder_objects.c - VA encoder objects abstraction
3  *
4  *  Copyright (C) 2013-2014 Intel Corporation
5  *    Author: Wind Yuan <feng.yuan@intel.com>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public License
9  *  as published by the Free Software Foundation; either version 2.1
10  *  of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301 USA
21  */
22 
23 #include "sysdeps.h"
24 #include "gstvaapiencoder_objects.h"
25 #include "gstvaapiencoder_priv.h"
26 #include "gstvaapisurfaceproxy_priv.h"
27 #include "gstvaapicompat.h"
28 #include "gstvaapiutils.h"
29 
30 #define DEBUG 1
31 #include "gstvaapidebug.h"
32 
33 #define GET_ENCODER(obj)    GST_VAAPI_ENCODER_CAST((obj)->parent_instance.codec)
34 #define GET_VA_DISPLAY(obj) GET_ENCODER(obj)->va_display
35 #define GET_VA_CONTEXT(obj) GET_ENCODER(obj)->va_context
36 
37 /* ------------------------------------------------------------------------- */
38 /* --- Encoder Packed Header                                             --- */
39 /* ------------------------------------------------------------------------- */
40 
41 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPackedHeader,
42     gst_vaapi_enc_packed_header);
43 
44 void
gst_vaapi_enc_packed_header_destroy(GstVaapiEncPackedHeader * header)45 gst_vaapi_enc_packed_header_destroy (GstVaapiEncPackedHeader * header)
46 {
47   vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->param_id);
48   vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->data_id);
49   header->param = NULL;
50   header->data = NULL;
51 }
52 
53 gboolean
gst_vaapi_enc_packed_header_create(GstVaapiEncPackedHeader * header,const GstVaapiCodecObjectConstructorArgs * args)54 gst_vaapi_enc_packed_header_create (GstVaapiEncPackedHeader * header,
55     const GstVaapiCodecObjectConstructorArgs * args)
56 {
57   gboolean success;
58 
59   header->param_id = VA_INVALID_ID;
60   header->data_id = VA_INVALID_ID;
61 
62   success = vaapi_create_buffer (GET_VA_DISPLAY (header),
63       GET_VA_CONTEXT (header),
64       VAEncPackedHeaderParameterBufferType,
65       args->param_size, args->param, &header->param_id, &header->param);
66   if (!success)
67     return FALSE;
68 
69   if (!args->data_size)
70     return TRUE;
71 
72   success = vaapi_create_buffer (GET_VA_DISPLAY (header),
73       GET_VA_CONTEXT (header),
74       VAEncPackedHeaderDataBufferType,
75       args->data_size, args->data, &header->data_id, &header->data);
76   if (!success)
77     return FALSE;
78   return TRUE;
79 }
80 
81 GstVaapiEncPackedHeader *
gst_vaapi_enc_packed_header_new(GstVaapiEncoder * encoder,gconstpointer param,guint param_size,gconstpointer data,guint data_size)82 gst_vaapi_enc_packed_header_new (GstVaapiEncoder * encoder,
83     gconstpointer param, guint param_size, gconstpointer data, guint data_size)
84 {
85   GstVaapiCodecObject *object;
86 
87   object = gst_vaapi_codec_object_new (&GstVaapiEncPackedHeaderClass,
88       GST_VAAPI_CODEC_BASE (encoder), param, param_size, data, data_size, 0);
89   return GST_VAAPI_ENC_PACKED_HEADER (object);
90 }
91 
92 gboolean
gst_vaapi_enc_packed_header_set_data(GstVaapiEncPackedHeader * header,gconstpointer data,guint data_size)93 gst_vaapi_enc_packed_header_set_data (GstVaapiEncPackedHeader * header,
94     gconstpointer data, guint data_size)
95 {
96   gboolean success;
97 
98   vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->data_id);
99   header->data = NULL;
100 
101   success = vaapi_create_buffer (GET_VA_DISPLAY (header),
102       GET_VA_CONTEXT (header),
103       VAEncPackedHeaderDataBufferType,
104       data_size, data, &header->data_id, &header->data);
105   if (!success)
106     return FALSE;
107   return TRUE;
108 }
109 
110 /* ------------------------------------------------------------------------- */
111 /* --- Encoder Sequence                                                  --- */
112 /* ------------------------------------------------------------------------- */
113 
114 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSequence, gst_vaapi_enc_sequence);
115 
116 void
gst_vaapi_enc_sequence_destroy(GstVaapiEncSequence * sequence)117 gst_vaapi_enc_sequence_destroy (GstVaapiEncSequence * sequence)
118 {
119   vaapi_destroy_buffer (GET_VA_DISPLAY (sequence), &sequence->param_id);
120   sequence->param = NULL;
121 }
122 
123 gboolean
gst_vaapi_enc_sequence_create(GstVaapiEncSequence * sequence,const GstVaapiCodecObjectConstructorArgs * args)124 gst_vaapi_enc_sequence_create (GstVaapiEncSequence * sequence,
125     const GstVaapiCodecObjectConstructorArgs * args)
126 {
127   gboolean success;
128 
129   sequence->param_id = VA_INVALID_ID;
130   success = vaapi_create_buffer (GET_VA_DISPLAY (sequence),
131       GET_VA_CONTEXT (sequence),
132       VAEncSequenceParameterBufferType,
133       args->param_size, args->param, &sequence->param_id, &sequence->param);
134   if (!success)
135     return FALSE;
136   return TRUE;
137 }
138 
139 GstVaapiEncSequence *
gst_vaapi_enc_sequence_new(GstVaapiEncoder * encoder,gconstpointer param,guint param_size)140 gst_vaapi_enc_sequence_new (GstVaapiEncoder * encoder,
141     gconstpointer param, guint param_size)
142 {
143   GstVaapiCodecObject *object;
144 
145   object = gst_vaapi_codec_object_new (&GstVaapiEncSequenceClass,
146       GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
147   return GST_VAAPI_ENC_SEQUENCE (object);
148 }
149 
150 /* ------------------------------------------------------------------------- */
151 /* --- Encoder Slice                                                     --- */
152 /* ------------------------------------------------------------------------- */
153 
154 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSlice, gst_vaapi_enc_slice);
155 
156 void
gst_vaapi_enc_slice_destroy(GstVaapiEncSlice * slice)157 gst_vaapi_enc_slice_destroy (GstVaapiEncSlice * slice)
158 {
159   if (slice->packed_headers) {
160     g_ptr_array_unref (slice->packed_headers);
161     slice->packed_headers = NULL;
162   }
163 
164   vaapi_destroy_buffer (GET_VA_DISPLAY (slice), &slice->param_id);
165   slice->param = NULL;
166 }
167 
168 gboolean
gst_vaapi_enc_slice_create(GstVaapiEncSlice * slice,const GstVaapiCodecObjectConstructorArgs * args)169 gst_vaapi_enc_slice_create (GstVaapiEncSlice * slice,
170     const GstVaapiCodecObjectConstructorArgs * args)
171 {
172   gboolean success;
173 
174   slice->param_id = VA_INVALID_ID;
175   success = vaapi_create_buffer (GET_VA_DISPLAY (slice),
176       GET_VA_CONTEXT (slice),
177       VAEncSliceParameterBufferType,
178       args->param_size, args->param, &slice->param_id, &slice->param);
179   if (!success)
180     return FALSE;
181 
182   slice->packed_headers = g_ptr_array_new_with_free_func ((GDestroyNotify)
183       gst_vaapi_mini_object_unref);
184   if (!slice->packed_headers)
185     return FALSE;
186 
187   return TRUE;
188 }
189 
190 GstVaapiEncSlice *
gst_vaapi_enc_slice_new(GstVaapiEncoder * encoder,gconstpointer param,guint param_size)191 gst_vaapi_enc_slice_new (GstVaapiEncoder * encoder,
192     gconstpointer param, guint param_size)
193 {
194   GstVaapiCodecObject *object;
195 
196   object = gst_vaapi_codec_object_new (&GstVaapiEncSliceClass,
197       GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
198   return GST_VAAPI_ENC_SLICE (object);
199 }
200 
201 /* ------------------------------------------------------------------------- */
202 /* --- Encoder Misc Parameter Buffer                                     --- */
203 /* ------------------------------------------------------------------------- */
204 
205 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncMiscParam, gst_vaapi_enc_misc_param);
206 
207 void
gst_vaapi_enc_misc_param_destroy(GstVaapiEncMiscParam * misc)208 gst_vaapi_enc_misc_param_destroy (GstVaapiEncMiscParam * misc)
209 {
210   vaapi_destroy_buffer (GET_VA_DISPLAY (misc), &misc->param_id);
211   misc->param = NULL;
212   misc->data = NULL;
213 }
214 
215 gboolean
gst_vaapi_enc_misc_param_create(GstVaapiEncMiscParam * misc,const GstVaapiCodecObjectConstructorArgs * args)216 gst_vaapi_enc_misc_param_create (GstVaapiEncMiscParam * misc,
217     const GstVaapiCodecObjectConstructorArgs * args)
218 {
219   gboolean success;
220 
221   misc->param_id = VA_INVALID_ID;
222   success = vaapi_create_buffer (GET_VA_DISPLAY (misc),
223       GET_VA_CONTEXT (misc),
224       VAEncMiscParameterBufferType,
225       args->param_size, args->param, &misc->param_id, &misc->param);
226   if (!success)
227     return FALSE;
228   return TRUE;
229 }
230 
231 GstVaapiEncMiscParam *
gst_vaapi_enc_misc_param_new(GstVaapiEncoder * encoder,VAEncMiscParameterType type,guint data_size)232 gst_vaapi_enc_misc_param_new (GstVaapiEncoder * encoder,
233     VAEncMiscParameterType type, guint data_size)
234 {
235   GstVaapiCodecObject *object;
236   GstVaapiEncMiscParam *misc;
237   VAEncMiscParameterBuffer *va_misc;
238 
239   object = gst_vaapi_codec_object_new (&GstVaapiEncMiscParamClass,
240       GST_VAAPI_CODEC_BASE (encoder),
241       NULL, sizeof (VAEncMiscParameterBuffer) + data_size, NULL, 0, 0);
242   if (!object)
243     return NULL;
244 
245   misc = GST_VAAPI_ENC_MISC_PARAM (object);
246   va_misc = misc->param;
247   va_misc->type = type;
248   misc->data = va_misc->data;
249   return misc;
250 }
251 
252 /* ------------------------------------------------------------------------- */
253 /* ---  Quantization Matrices                                            --- */
254 /* ------------------------------------------------------------------------- */
255 
256 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncQMatrix, gst_vaapi_enc_q_matrix);
257 
258 void
gst_vaapi_enc_q_matrix_destroy(GstVaapiEncQMatrix * q_matrix)259 gst_vaapi_enc_q_matrix_destroy (GstVaapiEncQMatrix * q_matrix)
260 {
261   vaapi_destroy_buffer (GET_VA_DISPLAY (q_matrix), &q_matrix->param_id);
262   q_matrix->param = NULL;
263 }
264 
265 gboolean
gst_vaapi_enc_q_matrix_create(GstVaapiEncQMatrix * q_matrix,const GstVaapiCodecObjectConstructorArgs * args)266 gst_vaapi_enc_q_matrix_create (GstVaapiEncQMatrix * q_matrix,
267     const GstVaapiCodecObjectConstructorArgs * args)
268 {
269   q_matrix->param_id = VA_INVALID_ID;
270   return vaapi_create_buffer (GET_VA_DISPLAY (q_matrix),
271       GET_VA_CONTEXT (q_matrix), VAQMatrixBufferType,
272       args->param_size, args->param, &q_matrix->param_id, &q_matrix->param);
273 }
274 
275 GstVaapiEncQMatrix *
gst_vaapi_enc_q_matrix_new(GstVaapiEncoder * encoder,gconstpointer param,guint param_size)276 gst_vaapi_enc_q_matrix_new (GstVaapiEncoder * encoder,
277     gconstpointer param, guint param_size)
278 {
279   GstVaapiCodecObject *object;
280 
281   object = gst_vaapi_codec_object_new (&GstVaapiEncQMatrixClass,
282       GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
283   if (!object)
284     return NULL;
285   return GST_VAAPI_ENC_Q_MATRIX_CAST (object);
286 }
287 
288 /* ------------------------------------------------------------------------- */
289 /* --- JPEG Huffman Tables                                               --- */
290 /* ------------------------------------------------------------------------- */
291 
292 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncHuffmanTable,
293     gst_vaapi_enc_huffman_table);
294 
295 void
gst_vaapi_enc_huffman_table_destroy(GstVaapiEncHuffmanTable * huf_table)296 gst_vaapi_enc_huffman_table_destroy (GstVaapiEncHuffmanTable * huf_table)
297 {
298   vaapi_destroy_buffer (GET_VA_DISPLAY (huf_table), &huf_table->param_id);
299   huf_table->param = NULL;
300 }
301 
302 gboolean
gst_vaapi_enc_huffman_table_create(GstVaapiEncHuffmanTable * huf_table,const GstVaapiCodecObjectConstructorArgs * args)303 gst_vaapi_enc_huffman_table_create (GstVaapiEncHuffmanTable * huf_table,
304     const GstVaapiCodecObjectConstructorArgs * args)
305 {
306   huf_table->param_id = VA_INVALID_ID;
307   return vaapi_create_buffer (GET_VA_DISPLAY (huf_table),
308       GET_VA_CONTEXT (huf_table), VAHuffmanTableBufferType, args->param_size,
309       args->param, &huf_table->param_id, (void **) &huf_table->param);
310 }
311 
312 GstVaapiEncHuffmanTable *
gst_vaapi_enc_huffman_table_new(GstVaapiEncoder * encoder,guint8 * data,guint data_size)313 gst_vaapi_enc_huffman_table_new (GstVaapiEncoder * encoder,
314     guint8 * data, guint data_size)
315 {
316   GstVaapiCodecObject *object;
317 
318   object = gst_vaapi_codec_object_new (&GstVaapiEncHuffmanTableClass,
319       GST_VAAPI_CODEC_BASE (encoder), data, data_size, NULL, 0, 0);
320   if (!object)
321     return NULL;
322   return GST_VAAPI_ENC_HUFFMAN_TABLE_CAST (object);
323 }
324 
325 /* ------------------------------------------------------------------------- */
326 /* --- Encoder Picture                                                   --- */
327 /* ------------------------------------------------------------------------- */
328 
329 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPicture, gst_vaapi_enc_picture);
330 
331 void
gst_vaapi_enc_picture_destroy(GstVaapiEncPicture * picture)332 gst_vaapi_enc_picture_destroy (GstVaapiEncPicture * picture)
333 {
334   if (picture->packed_headers) {
335     g_ptr_array_unref (picture->packed_headers);
336     picture->packed_headers = NULL;
337   }
338   if (picture->misc_params) {
339     g_ptr_array_unref (picture->misc_params);
340     picture->misc_params = NULL;
341   }
342   if (picture->slices) {
343     g_ptr_array_unref (picture->slices);
344     picture->slices = NULL;
345   }
346 
347   gst_vaapi_codec_object_replace (&picture->q_matrix, NULL);
348   gst_vaapi_codec_object_replace (&picture->huf_table, NULL);
349 
350   gst_vaapi_codec_object_replace (&picture->sequence, NULL);
351 
352 #if USE_H264_FEI_ENCODER
353   gst_vaapi_codec_object_replace (&picture->mvpred, NULL);
354   gst_vaapi_codec_object_replace (&picture->mbcntrl, NULL);
355   gst_vaapi_codec_object_replace (&picture->qp, NULL);
356   gst_vaapi_codec_object_replace (&picture->mbcode, NULL);
357   gst_vaapi_codec_object_replace (&picture->mv, NULL);
358   gst_vaapi_codec_object_replace (&picture->dist, NULL);
359 #endif
360 
361   gst_vaapi_surface_proxy_replace (&picture->proxy, NULL);
362   picture->surface_id = VA_INVALID_ID;
363   picture->surface = NULL;
364 
365   vaapi_destroy_buffer (GET_VA_DISPLAY (picture), &picture->param_id);
366   picture->param = NULL;
367 
368   if (picture->frame) {
369     gst_video_codec_frame_unref (picture->frame);
370     picture->frame = NULL;
371   }
372 }
373 
374 gboolean
gst_vaapi_enc_picture_create(GstVaapiEncPicture * picture,const GstVaapiCodecObjectConstructorArgs * args)375 gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
376     const GstVaapiCodecObjectConstructorArgs * args)
377 {
378   GstVideoCodecFrame *const frame = (GstVideoCodecFrame *) args->data;
379   gboolean success;
380 
381   picture->proxy = gst_video_codec_frame_get_user_data (frame);
382   if (!gst_vaapi_surface_proxy_ref (picture->proxy))
383     return FALSE;
384 
385   picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy);
386   if (!picture->surface)
387     return FALSE;
388 
389   picture->surface_id = GST_VAAPI_OBJECT_ID (picture->surface);
390   if (picture->surface_id == VA_INVALID_ID)
391     return FALSE;
392 
393   picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
394   picture->pts = GST_CLOCK_TIME_NONE;
395   picture->frame_num = 0;
396   picture->poc = 0;
397 
398   picture->param_id = VA_INVALID_ID;
399   picture->param_size = args->param_size;
400   success = vaapi_create_buffer (GET_VA_DISPLAY (picture),
401       GET_VA_CONTEXT (picture),
402       VAEncPictureParameterBufferType,
403       args->param_size, args->param, &picture->param_id, &picture->param);
404   if (!success)
405     return FALSE;
406   picture->param_size = args->param_size;
407 
408   picture->packed_headers = g_ptr_array_new_with_free_func ((GDestroyNotify)
409       gst_vaapi_mini_object_unref);
410   if (!picture->packed_headers)
411     return FALSE;
412 
413   picture->misc_params = g_ptr_array_new_with_free_func ((GDestroyNotify)
414       gst_vaapi_mini_object_unref);
415   if (!picture->misc_params)
416     return FALSE;
417 
418   picture->slices = g_ptr_array_new_with_free_func ((GDestroyNotify)
419       gst_vaapi_mini_object_unref);
420   if (!picture->slices)
421     return FALSE;
422 
423   picture->frame = gst_video_codec_frame_ref (frame);
424   return TRUE;
425 }
426 
427 GstVaapiEncPicture *
gst_vaapi_enc_picture_new(GstVaapiEncoder * encoder,gconstpointer param,guint param_size,GstVideoCodecFrame * frame)428 gst_vaapi_enc_picture_new (GstVaapiEncoder * encoder,
429     gconstpointer param, guint param_size, GstVideoCodecFrame * frame)
430 {
431   GstVaapiCodecObject *object;
432 
433   g_return_val_if_fail (frame != NULL, NULL);
434 
435   object = gst_vaapi_codec_object_new (&GstVaapiEncPictureClass,
436       GST_VAAPI_CODEC_BASE (encoder), param, param_size, frame, 0, 0);
437   return GST_VAAPI_ENC_PICTURE (object);
438 }
439 
440 void
gst_vaapi_enc_picture_set_sequence(GstVaapiEncPicture * picture,GstVaapiEncSequence * sequence)441 gst_vaapi_enc_picture_set_sequence (GstVaapiEncPicture * picture,
442     GstVaapiEncSequence * sequence)
443 {
444   g_return_if_fail (picture != NULL);
445   g_return_if_fail (sequence != NULL);
446 
447   gst_vaapi_codec_object_replace (&picture->sequence, sequence);
448 }
449 
450 void
gst_vaapi_enc_picture_add_packed_header(GstVaapiEncPicture * picture,GstVaapiEncPackedHeader * header)451 gst_vaapi_enc_picture_add_packed_header (GstVaapiEncPicture * picture,
452     GstVaapiEncPackedHeader * header)
453 {
454   g_return_if_fail (picture != NULL);
455   g_return_if_fail (header != NULL);
456 
457   g_ptr_array_add (picture->packed_headers,
458       gst_vaapi_codec_object_ref (header));
459 }
460 
461 void
gst_vaapi_enc_picture_add_misc_param(GstVaapiEncPicture * picture,GstVaapiEncMiscParam * misc)462 gst_vaapi_enc_picture_add_misc_param (GstVaapiEncPicture * picture,
463     GstVaapiEncMiscParam * misc)
464 {
465   g_return_if_fail (picture != NULL);
466   g_return_if_fail (misc != NULL);
467 
468   g_ptr_array_add (picture->misc_params, gst_vaapi_codec_object_ref (misc));
469 }
470 
471 void
gst_vaapi_enc_picture_add_slice(GstVaapiEncPicture * picture,GstVaapiEncSlice * slice)472 gst_vaapi_enc_picture_add_slice (GstVaapiEncPicture * picture,
473     GstVaapiEncSlice * slice)
474 {
475   g_return_if_fail (picture != NULL);
476   g_return_if_fail (slice != NULL);
477 
478   g_ptr_array_add (picture->slices, gst_vaapi_codec_object_ref (slice));
479 }
480 
481 void
gst_vaapi_enc_slice_add_packed_header(GstVaapiEncSlice * slice,GstVaapiEncPackedHeader * header)482 gst_vaapi_enc_slice_add_packed_header (GstVaapiEncSlice * slice,
483     GstVaapiEncPackedHeader * header)
484 {
485   g_return_if_fail (slice != NULL);
486   g_return_if_fail (header != NULL);
487 
488   g_ptr_array_add (slice->packed_headers, gst_vaapi_codec_object_ref (header));
489 }
490 
491 static gboolean
do_encode(VADisplay dpy,VAContextID ctx,VABufferID * buf_id,void ** buf_ptr)492 do_encode (VADisplay dpy, VAContextID ctx, VABufferID * buf_id, void **buf_ptr)
493 {
494   VAStatus status;
495 
496   vaapi_unmap_buffer (dpy, *buf_id, buf_ptr);
497 
498   status = vaRenderPicture (dpy, ctx, buf_id, 1);
499   if (!vaapi_check_status (status, "vaRenderPicture()"))
500     return FALSE;
501 
502   /* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
503   vaapi_destroy_buffer (dpy, buf_id);
504   return TRUE;
505 }
506 
507 gboolean
gst_vaapi_enc_picture_encode(GstVaapiEncPicture * picture)508 gst_vaapi_enc_picture_encode (GstVaapiEncPicture * picture)
509 {
510   GstVaapiEncSequence *sequence;
511   GstVaapiEncQMatrix *q_matrix;
512   GstVaapiEncHuffmanTable *huf_table;
513   VADisplay va_display;
514   VAContextID va_context;
515   VAStatus status;
516   guint i;
517 
518   g_return_val_if_fail (picture != NULL, FALSE);
519   g_return_val_if_fail (picture->surface_id != VA_INVALID_SURFACE, FALSE);
520 
521   va_display = GET_VA_DISPLAY (picture);
522   va_context = GET_VA_CONTEXT (picture);
523 
524   GST_DEBUG ("encode picture 0x%08x", picture->surface_id);
525 
526   status = vaBeginPicture (va_display, va_context, picture->surface_id);
527   if (!vaapi_check_status (status, "vaBeginPicture()"))
528     return FALSE;
529 
530   /* Submit Sequence parameter */
531   sequence = picture->sequence;
532   if (sequence && !do_encode (va_display, va_context,
533           &sequence->param_id, &sequence->param))
534     return FALSE;
535 
536   /* Submit Quantization matrix */
537   q_matrix = picture->q_matrix;
538   if (q_matrix && !do_encode (va_display, va_context,
539           &q_matrix->param_id, &q_matrix->param))
540     return FALSE;
541 
542   /* Submit huffman table */
543   huf_table = picture->huf_table;
544   if (huf_table && !do_encode (va_display, va_context,
545           &huf_table->param_id, (void **) &huf_table->param))
546     return FALSE;
547 
548   /* Submit Packed Headers */
549   for (i = 0; i < picture->packed_headers->len; i++) {
550     GstVaapiEncPackedHeader *const header =
551         g_ptr_array_index (picture->packed_headers, i);
552     if (!do_encode (va_display, va_context,
553             &header->param_id, &header->param) ||
554         !do_encode (va_display, va_context, &header->data_id, &header->data))
555       return FALSE;
556   }
557 
558   /* Submit Picture parameter */
559   if (!do_encode (va_display, va_context, &picture->param_id, &picture->param))
560     return FALSE;
561 
562   /* Submit Misc Params */
563   for (i = 0; i < picture->misc_params->len; i++) {
564     GstVaapiEncMiscParam *const misc =
565         g_ptr_array_index (picture->misc_params, i);
566     if (!do_encode (va_display, va_context, &misc->param_id, &misc->param))
567       return FALSE;
568   }
569 
570   /* Submit Slice parameters */
571   for (i = 0; i < picture->slices->len; i++) {
572     GstVaapiEncSlice *const slice = g_ptr_array_index (picture->slices, i);
573     guint j;
574 
575     /* Submit packed_slice_header and packed_raw_data */
576     for (j = 0; j < slice->packed_headers->len; j++) {
577       GstVaapiEncPackedHeader *const header =
578           g_ptr_array_index (slice->packed_headers, j);
579       if (!do_encode (va_display, va_context,
580               &header->param_id, &header->param) ||
581           !do_encode (va_display, va_context, &header->data_id, &header->data))
582         return FALSE;
583     }
584     if (!do_encode (va_display, va_context, &slice->param_id, &slice->param))
585       return FALSE;
586   }
587 
588   status = vaEndPicture (va_display, va_context);
589   if (!vaapi_check_status (status, "vaEndPicture()"))
590     return FALSE;
591   return TRUE;
592 }
593