• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /*
26  * Simple H.264/AVC temporal scalability encoder based on libVA.
27  *
28  */
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <getopt.h>
34 #include <unistd.h>
35 
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <assert.h>
41 #include <time.h>
42 #include <math.h>
43 
44 #include <pthread.h>
45 
46 #include <va/va.h>
47 #include "va_display.h"
48 
49 #define SLICE_TYPE_P                    0
50 #define SLICE_TYPE_B                    1
51 #define SLICE_TYPE_I                    2
52 
53 #define IS_I_SLICE(type)                (SLICE_TYPE_I == (type) || SLICE_TYPE_I == (type - 5))
54 #define IS_P_SLICE(type)                (SLICE_TYPE_P == (type) || SLICE_TYPE_P == (type - 5))
55 #define IS_B_SLICE(type)                (SLICE_TYPE_B == (type) || SLICE_TYPE_B == (type - 5))
56 
57 #define NAL_REF_IDC_NONE                0
58 #define NAL_REF_IDC_LOW                 1
59 #define NAL_REF_IDC_MEDIUM              2
60 #define NAL_REF_IDC_HIGH                3
61 
62 #define NAL_NON_IDR                     1
63 #define NAL_IDR                         5
64 #define NAL_SEI                 6
65 #define NAL_SPS                         7
66 #define NAL_PPS                         8
67 #define NAL_PREFIX                      14
68 #define NAL_SUBSET_SPS                  15
69 
70 #define ENTROPY_MODE_CAVLC              0
71 #define ENTROPY_MODE_CABAC              1
72 
73 #define PROFILE_IDC_BASELINE            66
74 #define PROFILE_IDC_MAIN                77
75 #define PROFILE_IDC_SCALABLE_BASELINE   83
76 #define PROFILE_IDC_SCALABLE_HIGH       86
77 #define PROFILE_IDC_HIGH                100
78 
79 #define SRC_SURFACE_IN_ENCODING         0
80 #define SRC_SURFACE_IN_STORAGE          1
81 
82 #define NUM_SURFACES                    32
83 
84 #define ARRAY_ELEMS(a)                  (sizeof(a) / sizeof((a)[0]))
85 
86 #define CHECK_VASTATUS(va_status, func)                                 \
87     if (va_status != VA_STATUS_SUCCESS) {                               \
88         fprintf(stderr,"%s:%s (%d) failed, exit\n", __func__, func, __LINE__); \
89         exit(1);                                                        \
90     }
91 
92 #define CHECK_CONDITION(cond)                                                \
93     if(!(cond))                                                              \
94     {                                                                        \
95         fprintf(stderr, "Unexpected condition: %s:%d\n", __func__, __LINE__); \
96         exit(1);                                                             \
97     }
98 
99 #define MAX_SLICES                      32
100 #define MAX_LAYERS                      4
101 
102 #define MIN(a, b)                       ((a) > (b) ? (b) : (a))
103 #define MAX(a, b)                       ((a) > (b) ? (a) : (b))
104 
105 static VASurfaceID src_surfaces[NUM_SURFACES];
106 static VASurfaceID rec_surfaces[NUM_SURFACES];
107 static int src_surface_status[NUM_SURFACES];
108 
109 static int temporal_ids_in_bgop[16] = { // index is (encoding order) % gop_size - 1, available from the 2nd encoded frame
110     0,                                  /* temporal 0 */
111     1,                                  /* temporal 1 */
112     2, 2,                               /* temporal 2 */
113     3, 3, 3, 3,                         /* temporal 3 */
114     4, 4, 4, 4, 4, 4, 4, 4              /* temporal 4 */
115 };
116 
117 static int temporal_ids_in_pgop[16] = { // index is (encoding order) % gop_size - 1, available from the 2nd encoded frame
118     1, 2, 1, 3,                         // each element is (the number of temporal layers - temporal id)
119     1, 2, 1, 3,
120     1, 2, 1, 3,
121     1, 2, 1, 3,
122 };
123 
124 static int gop_factors_in_bgop[16] = {
125     1,
126     1,
127     1, 3,
128     1, 3, 5, 7,
129     1, 3, 5, 7, 9, 11, 13, 15
130 };
131 
132 static float frame_rates[4] = {
133     7.5,
134     15,
135     30,
136     60,
137 };
138 
139 static VAProfile g_va_profiles[] = {
140     VAProfileH264High,
141     VAProfileH264ConstrainedBaseline,
142 };
143 
144 typedef struct _svcenc_surface {
145     int slot_in_surfaces; /* index in src_surfaces and rec_surfaces */
146     int coding_order;
147     int display_order;
148     int temporal_id;
149     int frame_num;
150     int poc;
151     unsigned int is_intra : 1;
152     unsigned int is_idr : 1;
153     unsigned int is_ref : 1;
154     VAEncPictureType picture_type;
155     VASurfaceID rec_surface;
156 } svcenc_surface;
157 
158 static svcenc_surface ref_frames[16], ref_list0[32], ref_list1[32];
159 
160 static pthread_mutex_t upload_mutex = PTHREAD_MUTEX_INITIALIZER;
161 static pthread_cond_t upload_cond = PTHREAD_COND_INITIALIZER;
162 
163 struct upload_task_t {
164     void *next;
165     unsigned int display_order;
166     unsigned int surface;
167 };
168 
169 struct svcenc_context {
170     /* parameter info */
171     FILE *ifp;  /* a FILE pointer for source YUV file */
172     FILE *ofp;  /* a FILE pointer for output SVC file */
173     int width;
174     int height;
175     int frame_size;
176     int num_pictures;
177     int num_slices;
178     int qp;     /* quantisation parameter, default value is 26 */
179     unsigned char *frame_data_buffer;   /* buffer for input surface, the length is the maximum frame_size */
180     int gop_size;
181     int max_num_ref_frames;
182     int num_ref_frames;
183     int hierarchical_levels;
184     int layer_brc;
185 
186     /* the info for next picture in encoding order */
187     svcenc_surface next_svcenc_surface;
188 
189     /* GOP info */
190     int intra_idr_period;
191     int intra_period;
192     int ip_period;
193     int num_remainder_bframes;
194     int gop_type;       /* 0: p hierarchical, 1: B hierarchical, default is 0 */
195 
196     /* bitrate info */
197     int rate_control_mode;
198     int bits_per_kbps;
199     int framerate_per_100s;
200     int i_initial_cpb_removal_delay;
201     int i_initial_cpb_removal_delay_offset;
202     int i_initial_cpb_removal_delay_length;
203     int i_cpb_removal_delay;
204     int i_cpb_removal_delay_length;
205     int i_dpb_output_delay_length;
206     int time_offset_length;
207 
208     unsigned long long idr_frame_num;
209     unsigned long long prev_idr_cpb_removal;
210     unsigned long long current_idr_cpb_removal;
211     unsigned long long current_cpb_removal;
212 
213     /* This is relative to the current_cpb_removal */
214     unsigned int current_dpb_removal_delta;
215 
216     int profile_idc;
217     int constraint_set_flag;
218 
219     int svc_profile_idc;
220     int svc_constraint_set_flag;
221 
222     /* reordering info for l0/l1,
223      * bit0-3: ref_pic_list_modification_flag_lX (X=0,1),
224      * bit4-7: modification_of_pic_nums_idc,
225      * bit8-15: abs_diff_pic_num_minus1
226      * bit16-23: num_ref_idx_active_override_flag
227      * bit24-31: num_ref_idx_lX_active_minus1 (X=0,1),
228      */
229     unsigned int reordering_info[2];
230 
231     /* VA info */
232     VADisplay va_dpy;
233     VAProfile profile;
234     VAEncSequenceParameterBufferH264 seq_param;
235     VAEncPictureParameterBufferH264 pic_param;
236     VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
237     VAContextID context_id;
238     VAConfigID config_id;
239     VABufferID seq_param_buf_id;                /* Sequence level parameter */
240     VABufferID pic_param_buf_id;                /* Picture level parameter */
241     VABufferID slice_param_buf_id[MAX_SLICES];  /* Slice level parameter, multil slices */
242     VABufferID codedbuf_buf_id;                 /* Output buffer, compressed data */
243     VABufferID packed_sei_scalability_info_header_param_buf_id;
244     VABufferID packed_sei_scalability_info_buf_id;
245     VABufferID packed_seq_header_param_buf_id;
246     VABufferID packed_seq_buf_id;
247     VABufferID packed_svc_seq_header_param_buf_id;
248     VABufferID packed_svc_seq_buf_id;
249     VABufferID packed_pic_header_param_buf_id;
250     VABufferID packed_pic_buf_id;
251     VABufferID packed_sei_header_param_buf_id;   /* the SEI buffer */
252     VABufferID packed_sei_buf_id;
253     VABufferID misc_parameter_layer_structure_buf_id;
254     VABufferID misc_parameter_ratecontrol_buf_id[MAX_LAYERS];
255     VABufferID misc_parameter_framerate_buf_id[MAX_LAYERS];
256     VABufferID misc_parameter_hrd_buf_id;
257     VABufferID packed_slice_header_param_buf_id[MAX_SLICES];
258     VABufferID packed_slice_header_data_buf_id[MAX_SLICES];
259     VABufferID packed_prefix_nal_unit_param_buf_id[MAX_SLICES];
260     VABufferID packed_prefix_nal_unit_data_buf_id[MAX_SLICES];
261 
262     /* thread info */
263     pthread_t upload_thread;
264     struct upload_task_t *upload_task_header;
265     struct upload_task_t *upload_task_tail;
266 };
267 
268 /* bitstream */
269 #define BITSTREAM_ALLOCATE_STEPPING     4096
270 
271 struct __bitstream {
272     unsigned int *buffer;
273     int bit_offset;
274     int max_size_in_dword;
275 };
276 
277 typedef struct __bitstream bitstream;
278 
279 static unsigned int
va_swap32(unsigned int val)280 va_swap32(unsigned int val)
281 {
282     unsigned char *pval = (unsigned char *)&val;
283 
284     return ((pval[0] << 24)     |
285             (pval[1] << 16)     |
286             (pval[2] << 8)      |
287             (pval[3] << 0));
288 }
289 
290 static void
bitstream_start(bitstream * bs)291 bitstream_start(bitstream *bs)
292 {
293     bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
294     bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
295     bs->bit_offset = 0;
296 }
297 
298 static void
bitstream_end(bitstream * bs)299 bitstream_end(bitstream *bs)
300 {
301     int pos = (bs->bit_offset >> 5);
302     int bit_offset = (bs->bit_offset & 0x1f);
303     int bit_left = 32 - bit_offset;
304 
305     if (bit_offset) {
306         bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
307     }
308 }
309 
310 static void
bitstream_put_ui(bitstream * bs,unsigned int val,int size_in_bits)311 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
312 {
313     int pos = (bs->bit_offset >> 5);
314     int bit_offset = (bs->bit_offset & 0x1f);
315     int bit_left = 32 - bit_offset;
316 
317     if (!size_in_bits)
318         return;
319 
320     bs->bit_offset += size_in_bits;
321 
322     if (bit_left > size_in_bits) {
323         bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
324     } else {
325         size_in_bits -= bit_left;
326         bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
327         bs->buffer[pos] = va_swap32(bs->buffer[pos]);
328 
329         if (pos + 1 == bs->max_size_in_dword) {
330             bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
331             bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
332             assert(bs->buffer);
333         }
334 
335         bs->buffer[pos + 1] = val;
336     }
337 }
338 
339 static void
bitstream_put_ue(bitstream * bs,unsigned int val)340 bitstream_put_ue(bitstream *bs, unsigned int val)
341 {
342     int size_in_bits = 0;
343     int tmp_val = ++val;
344 
345     while (tmp_val) {
346         tmp_val >>= 1;
347         size_in_bits++;
348     }
349 
350     bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
351     bitstream_put_ui(bs, val, size_in_bits);
352 }
353 
354 static void
bitstream_put_se(bitstream * bs,int val)355 bitstream_put_se(bitstream *bs, int val)
356 {
357     unsigned int new_val;
358 
359     if (val <= 0)
360         new_val = -2 * val;
361     else
362         new_val = 2 * val - 1;
363 
364     bitstream_put_ue(bs, new_val);
365 }
366 
367 static void
bitstream_byte_aligning(bitstream * bs,int bit)368 bitstream_byte_aligning(bitstream *bs, int bit)
369 {
370     int bit_offset = (bs->bit_offset & 0x7);
371     int bit_left = 8 - bit_offset;
372     int new_val;
373 
374     if (!bit_offset)
375         return;
376 
377     assert(bit == 0 || bit == 1);
378 
379     if (bit)
380         new_val = (1 << bit_left) - 1;
381     else
382         new_val = 0;
383 
384     bitstream_put_ui(bs, new_val, bit_left);
385 }
386 
387 static void
rbsp_trailing_bits(bitstream * bs)388 rbsp_trailing_bits(bitstream *bs)
389 {
390     bitstream_put_ui(bs, 1, 1);
391     bitstream_byte_aligning(bs, 0);
392 }
393 
394 static void
nal_start_code_prefix(bitstream * bs)395 nal_start_code_prefix(bitstream *bs)
396 {
397     bitstream_put_ui(bs, 0x00000001, 32);
398 }
399 
400 static void
nal_header(bitstream * bs,int nal_ref_idc,int nal_unit_type)401 nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
402 {
403     bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
404     bitstream_put_ui(bs, nal_ref_idc, 2);
405     bitstream_put_ui(bs, nal_unit_type, 5);
406 }
407 
408 static void
sps_data(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,bitstream * bs)409 sps_data(struct svcenc_context *ctx,
410          const VAEncSequenceParameterBufferH264 *seq_param,
411          bitstream *bs)
412 {
413     bitstream_put_ui(bs, ctx->profile_idc, 8);               /* profile_idc */
414     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 1), 1);                          /* constraint_set0_flag */
415     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 2), 1);                          /* constraint_set1_flag */
416     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 4), 1);                          /* constraint_set2_flag */
417     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 8), 1);                          /* constraint_set3_flag */
418     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 16), 1);                         /* constraint_set4_flag */
419     bitstream_put_ui(bs, !!(ctx->constraint_set_flag & 32), 1);                         /* constraint_set5_flag */
420     bitstream_put_ui(bs, 0, 2);                         /* reserved_zero_2bits */
421     bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
422     bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
423 
424     if (ctx->profile_idc == PROFILE_IDC_HIGH ||
425         ctx->profile_idc == PROFILE_IDC_SCALABLE_HIGH ||
426         ctx->profile_idc == PROFILE_IDC_SCALABLE_BASELINE) {
427         bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */
428         bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
429         bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
430         bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
431         bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
432     }
433 
434     bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
435     bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
436 
437     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
438         bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
439     else {
440         assert(0);
441     }
442 
443     bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
444     bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
445 
446     bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
447     bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
448     bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
449 
450     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
451         assert(0);
452     }
453 
454     bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
455     bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
456 
457     if (seq_param->frame_cropping_flag) {
458         bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
459         bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
460         bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
461         bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
462     }
463 
464     if (ctx->bits_per_kbps < 0) {
465         bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
466     } else {
467         bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
468         bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
469         bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
470         bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
471         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
472         bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
473         {
474             bitstream_put_ui(bs, seq_param->num_units_in_tick, 32);
475             bitstream_put_ui(bs, seq_param->time_scale, 32);
476             bitstream_put_ui(bs, 1, 1);
477         }
478         bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
479         {
480             // hrd_parameters
481             bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
482             bitstream_put_ui(bs, 0, 4); /* bit_rate_scale */
483             bitstream_put_ui(bs, 2, 4); /* cpb_size_scale */
484 
485             /* the bits_per_kbps is in kbps */
486             bitstream_put_ue(bs, (((ctx->bits_per_kbps * 1024) >> 6) - 1)); /* bit_rate_value_minus1[0] */
487             bitstream_put_ue(bs, ((ctx->bits_per_kbps * 8 * 1024) >> 6) - 1); /* cpb_size_value_minus1[0] */
488             bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
489 
490             /* initial_cpb_removal_delay_length_minus1 */
491             bitstream_put_ui(bs, (ctx->i_initial_cpb_removal_delay_length - 1), 5);
492             /* cpb_removal_delay_length_minus1 */
493             bitstream_put_ui(bs, (ctx->i_cpb_removal_delay_length - 1), 5);
494             /* dpb_output_delay_length_minus1 */
495             bitstream_put_ui(bs, (ctx->i_dpb_output_delay_length - 1), 5);
496             /* time_offset_length  */
497             bitstream_put_ui(bs, (ctx->time_offset_length - 1), 5);
498         }
499 
500         bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
501         bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */
502 
503         bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
504         bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
505     }
506 }
507 
508 static void
sps_svc_extension(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * sps_param,bitstream * bs)509 sps_svc_extension(struct svcenc_context *ctx,
510                   const VAEncSequenceParameterBufferH264 *sps_param,
511                   bitstream *bs)
512 {
513     bitstream_put_ui(bs, 0, 1); /* inter_layer_deblocking_filter_control_present_flag */
514     bitstream_put_ui(bs, 0, 2); /* extended_spatial_scalability_idc */
515 
516     /* if (ChromaArrayType == 1) */
517     bitstream_put_ui(bs, 0, 1); /* chroma_phase_x_plus1_flag */
518     bitstream_put_ui(bs, 1, 2); /* chroma_phase_y_plus1 */
519 
520 #if 0
521     if (extended_spatial_scalability_idc == 1) {
522         /* if (ChromaArrayType > 0) */
523         bitstream_put_ui(bs, 0, 1); /* seq_ref_layer_chroma_phase_x_plus1_flag */
524         bitstream_put_ui(bs, 0, 2); /* seq_ref_layer_chroma_phase_y_plus1 */
525 
526         bitstream_put_se(bs, 0); /* seq_scaled_ref_layer_left_offset */
527         bitstream_put_se(bs, 0); /* seq_scaled_ref_layer_top_offset */
528         bitstream_put_se(bs, 0); /* seq_scaled_ref_layer_right_offset */
529         bitstream_put_se(bs, 0); /* seq_scaled_ref_layer_bottom_offset */
530     }
531 #endif
532 
533     bitstream_put_ui(bs, 0, 1); /* seq_tcoeff_level_prediction_flag */
534 
535 #if 0
536     if (seq_tcoeff_level_prediction_flag)
537         bitstream_put_ui(bs, 0, 1); /* adaptive_tcoeff_level_prediction_flag */
538 #endif
539 
540     bitstream_put_ui(bs, 0, 1); /* slice_header_restriction_flag */
541 }
542 
543 static void
sps_svc_vui_parameters_extension(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * sps_param,bitstream * bs)544 sps_svc_vui_parameters_extension(struct svcenc_context *ctx,
545                                  const VAEncSequenceParameterBufferH264 *sps_param,
546                                  bitstream *bs)
547 {
548     bitstream_put_ui(bs, 0, 1); /* svc_vui_parameters_present_flag */
549 }
550 
551 static void
sps_additional_extension2(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * sps_param,bitstream * bs)552 sps_additional_extension2(struct svcenc_context *ctx,
553                           const VAEncSequenceParameterBufferH264 *sps_param,
554                           bitstream *bs)
555 {
556     bitstream_put_ui(bs, 0, 1); /* additional_extension2_flag */
557 }
558 
559 static void
pps_rbsp(struct svcenc_context * ctx,const VAEncPictureParameterBufferH264 * pic_param,bitstream * bs)560 pps_rbsp(struct svcenc_context *ctx,
561          const VAEncPictureParameterBufferH264 *pic_param,
562          bitstream *bs)
563 {
564     bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
565     bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
566 
567     bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
568 
569     bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
570 
571     bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
572 
573     bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
574     bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
575 
576     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
577     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);    /* weighted_bipred_idc: 0 */
578 
579     bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
580     bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
581     bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
582 
583     bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
584     bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
585     bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
586 
587     /* more_rbsp_data */
588     bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
589     bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
590     bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset);     /*second_chroma_qp_index_offset */
591 
592     rbsp_trailing_bits(bs);
593 }
594 
595 static int
build_packed_seq_buffer(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,unsigned char ** header_buffer)596 build_packed_seq_buffer(struct svcenc_context *ctx,
597                         const VAEncSequenceParameterBufferH264 *seq_param,
598                         unsigned char **header_buffer)
599 {
600     bitstream bs;
601 
602     bitstream_start(&bs);
603 
604     nal_start_code_prefix(&bs);
605     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
606 
607     sps_data(ctx, seq_param, &bs);
608     rbsp_trailing_bits(&bs);     /* rbsp_trailing_bits */
609 
610     bitstream_end(&bs);
611 
612     *header_buffer = (unsigned char *)bs.buffer;
613     return bs.bit_offset;
614 }
615 
616 static int
build_packed_subset_seq_buffer(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,unsigned char ** header_buffer)617 build_packed_subset_seq_buffer(struct svcenc_context *ctx,
618                                const VAEncSequenceParameterBufferH264 *seq_param,
619                                unsigned char **header_buffer)
620 {
621     bitstream bs;
622 
623     bitstream_start(&bs);
624 
625     nal_start_code_prefix(&bs);
626     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SUBSET_SPS);
627 
628     sps_data(ctx, seq_param, &bs);
629     sps_svc_extension(ctx, seq_param, &bs);
630     sps_svc_vui_parameters_extension(ctx, seq_param, &bs);
631     sps_additional_extension2(ctx, seq_param, &bs);
632     rbsp_trailing_bits(&bs);     /* rbsp_trailing_bits */
633 
634     bitstream_end(&bs);
635 
636     *header_buffer = (unsigned char *)bs.buffer;
637     return bs.bit_offset;
638 }
639 
640 static int
build_packed_pic_buffer(struct svcenc_context * ctx,const VAEncPictureParameterBufferH264 * pic_param,unsigned char ** header_buffer)641 build_packed_pic_buffer(struct svcenc_context *ctx,
642                         const VAEncPictureParameterBufferH264 *pic_param,
643                         unsigned char **header_buffer)
644 {
645     bitstream bs;
646 
647     bitstream_start(&bs);
648     nal_start_code_prefix(&bs);
649     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
650     pps_rbsp(ctx, pic_param, &bs);
651     bitstream_end(&bs);
652 
653     *header_buffer = (unsigned char *)bs.buffer;
654     return bs.bit_offset;
655 }
656 
657 static int
build_packed_sei_buffering_period_buffer(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,int frame_num,unsigned char ** sei_buffer)658 build_packed_sei_buffering_period_buffer(struct svcenc_context *ctx,
659         const VAEncSequenceParameterBufferH264 *seq_param,
660         int frame_num,
661         unsigned char **sei_buffer)
662 {
663     bitstream sei_bp_bs;
664 
665     if (ctx->rate_control_mode & VA_RC_CQP ||
666         frame_num) {
667         *sei_buffer = NULL;
668         return 0;
669     }
670 
671     bitstream_start(&sei_bp_bs);
672     bitstream_put_ue(&sei_bp_bs, seq_param->seq_parameter_set_id);       /* seq_parameter_set_id */
673     /* SEI buffer period info */
674     /* NALHrdBpPresentFlag == 1 */
675     bitstream_put_ui(&sei_bp_bs, ctx->i_initial_cpb_removal_delay, ctx->i_initial_cpb_removal_delay_length);
676     bitstream_put_ui(&sei_bp_bs, ctx->i_initial_cpb_removal_delay_offset, ctx->i_initial_cpb_removal_delay_length);
677 
678     if (sei_bp_bs.bit_offset & 0x7) {
679         bitstream_put_ui(&sei_bp_bs, 1, 1);
680     }
681 
682     bitstream_end(&sei_bp_bs);
683 
684     *sei_buffer = (unsigned char *)sei_bp_bs.buffer;
685 
686     return (sei_bp_bs.bit_offset + 7) / 8;
687 }
688 
689 static int
build_packed_sei_pic_timing_buffer(struct svcenc_context * ctx,int frame_num,unsigned char ** sei_buffer)690 build_packed_sei_pic_timing_buffer(struct svcenc_context *ctx, int frame_num, unsigned char **sei_buffer)
691 {
692     bitstream sei_pic_bs;
693     unsigned int cpb_removal_delay;
694 
695     if (ctx->rate_control_mode & VA_RC_CQP) {
696         *sei_buffer = 0;
697         return 0;
698     }
699 
700     /* SEI pic timing info */
701     bitstream_start(&sei_pic_bs);
702 
703     /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
704      * which is derived as 1 if one of the following conditions is true:
705      * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
706      * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
707      */
708     cpb_removal_delay = (ctx->current_cpb_removal - ctx->prev_idr_cpb_removal);
709     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, ctx->i_cpb_removal_delay_length);
710     bitstream_put_ui(&sei_pic_bs, ctx->current_dpb_removal_delta, ctx->i_dpb_output_delay_length);
711 
712     if (sei_pic_bs.bit_offset & 0x7) {
713         bitstream_put_ui(&sei_pic_bs, 1, 1);
714     }
715 
716     /* The pic_structure_present_flag determines whether the pic_structure
717      * info is written into the SEI pic timing info.
718      * Currently it is set to zero.
719      */
720     bitstream_end(&sei_pic_bs);
721 
722     *sei_buffer = (unsigned char *)sei_pic_bs.buffer;
723 
724     return (sei_pic_bs.bit_offset + 7) / 8;
725 }
726 
727 static int
build_packed_sei_scalability_info_buffer(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,const VAEncPictureParameterBufferH264 * pic_param,int frame_num,unsigned char ** sei_buffer)728 build_packed_sei_scalability_info_buffer(struct svcenc_context *ctx,
729         const VAEncSequenceParameterBufferH264 *seq_param,
730         const VAEncPictureParameterBufferH264 *pic_param,
731         int frame_num,
732         unsigned char **sei_buffer)
733 {
734     bitstream scalability_info_bs;
735     int i;
736 
737     if (frame_num) { // non IDR
738         *sei_buffer = NULL;
739         return 0;
740     }
741 
742     /* Write scalability_info */
743     bitstream_start(&scalability_info_bs);
744 
745     bitstream_put_ui(&scalability_info_bs, 0, 1);       // temporal_id_nesting_flag: false
746     bitstream_put_ui(&scalability_info_bs, 0, 1);       // priority_layer_info_present_flag: false
747     bitstream_put_ui(&scalability_info_bs, 0, 1);       // priority_id_setting_flag: false
748     bitstream_put_ue(&scalability_info_bs, ctx->hierarchical_levels - 1); // num_layers_minus1
749 
750     for (i = 0; i < ctx->hierarchical_levels; i++) {
751         bitstream_put_ue(&scalability_info_bs, i);      // layer_id[i]
752         bitstream_put_ui(&scalability_info_bs, 0, 6);   // priority_id[i[
753         bitstream_put_ui(&scalability_info_bs, 0, 1);   // discardable_flag[i]
754         bitstream_put_ui(&scalability_info_bs, 0, 3);   // dependency_id[i]
755         bitstream_put_ui(&scalability_info_bs, 0, 4);   // quality_id[i]
756         bitstream_put_ui(&scalability_info_bs, i, 3);   // temporal_id[i]
757         bitstream_put_ui(&scalability_info_bs, 0, 1);   // sub_pic_layer_flag[i]
758         bitstream_put_ui(&scalability_info_bs, 0, 1);   // sub_region_layer_flag[i]
759         bitstream_put_ui(&scalability_info_bs, 0, 1);   // iroi_division_info_present_flag[i]
760         bitstream_put_ui(&scalability_info_bs, 0, 1);   // profile_level_info_present_flag[i]
761         bitstream_put_ui(&scalability_info_bs, 0, 1);   // bitrate_info_present_flag[i]
762         bitstream_put_ui(&scalability_info_bs, 1, 1);   // frm_rate_info_present_flag[i]
763         bitstream_put_ui(&scalability_info_bs, 1, 1);   // frm_size_info_present_flag[i]
764         bitstream_put_ui(&scalability_info_bs, 0, 1);   // layer_dependency_info_present_flag[i]
765         bitstream_put_ui(&scalability_info_bs, 0, 1);   // parameter_sets_info_present_flag[i]
766         bitstream_put_ui(&scalability_info_bs, 0, 1);   // bitstream_restriction_info_present_flag[i]
767         bitstream_put_ui(&scalability_info_bs, 0, 1);   // exact_interlayer_pred_flag[i]
768         bitstream_put_ui(&scalability_info_bs, 0, 1);   // layer_conversion_flag[i]
769         bitstream_put_ui(&scalability_info_bs, 0, 1);   // layer_output_flag[i]
770 
771         bitstream_put_ui(&scalability_info_bs, 0, 2);   // constant_frm_bitrate_idc[i]
772         bitstream_put_ui(&scalability_info_bs, (int)floor(frame_rates[i] * 256 + 0.5), 16);     // avg_frm_rate
773 
774         bitstream_put_ue(&scalability_info_bs, seq_param->picture_width_in_mbs - 1);    // frm_width_in_mbs_minus1
775         bitstream_put_ue(&scalability_info_bs, seq_param->picture_height_in_mbs - 1);   // frm_height_in_mbs_minus1
776 
777         bitstream_put_ue(&scalability_info_bs, 0);      // layer_dependency_info_src_layer_id_delta[i]
778         bitstream_put_ue(&scalability_info_bs, 0);      // parameter_sets_info_src_layer_id_delta[i]
779     }
780 
781     rbsp_trailing_bits(&scalability_info_bs);
782     bitstream_end(&scalability_info_bs);
783 
784     *sei_buffer = (unsigned char *)scalability_info_bs.buffer;
785 
786     return (scalability_info_bs.bit_offset + 7) / 8;
787 }
788 
789 static void
svcenc_update_sei_info(struct svcenc_context * ctx,svcenc_surface * current_surface)790 svcenc_update_sei_info(struct svcenc_context *ctx, svcenc_surface *current_surface)
791 {
792     unsigned long long frame_interval;
793 
794     if (!(ctx->rate_control_mode & VA_RC_CBR)) {
795         return;
796     }
797 
798     frame_interval = current_surface->coding_order - ctx->idr_frame_num;
799 
800     if (current_surface->is_idr) {
801         ctx->current_cpb_removal = ctx->prev_idr_cpb_removal + frame_interval * 2;
802         ctx->idr_frame_num = current_surface->coding_order;
803         ctx->current_idr_cpb_removal = ctx->current_cpb_removal;
804 
805         if (ctx->ip_period)
806             ctx->current_dpb_removal_delta = (ctx->ip_period + 1) * 2;
807         else
808             ctx->current_dpb_removal_delta = 2;
809     } else {
810         ctx->current_cpb_removal = ctx->current_idr_cpb_removal + frame_interval * 2;
811 
812         if (current_surface->picture_type == VAEncPictureTypeIntra ||
813             current_surface->picture_type == VAEncPictureTypePredictive) {
814             if (ctx->ip_period)
815                 ctx->current_dpb_removal_delta = (ctx->ip_period + 1) * 2;
816             else
817                 ctx->current_dpb_removal_delta = 2;
818         } else
819             ctx->current_dpb_removal_delta = 2;
820     }
821 }
822 
823 static int
build_packed_sei_buffer(struct svcenc_context * ctx,const VAEncSequenceParameterBufferH264 * seq_param,const VAEncPictureParameterBufferH264 * pic_param,svcenc_surface * current_surface,unsigned char ** sei_buffer)824 build_packed_sei_buffer(struct svcenc_context *ctx,
825                         const VAEncSequenceParameterBufferH264 *seq_param,
826                         const VAEncPictureParameterBufferH264 *pic_param,
827                         svcenc_surface *current_surface,
828                         unsigned char **sei_buffer)
829 {
830     unsigned char *scalability_info_buffer = NULL, *buffering_period_buffer = NULL, *pic_timing_buffer = NULL;
831     int scalability_info_size = 0, buffering_period_size = 0,  pic_timing_size = 0;
832     bitstream nal_bs;
833     int i;
834 
835     svcenc_update_sei_info(ctx, current_surface);
836 
837     buffering_period_size = build_packed_sei_buffering_period_buffer(ctx, seq_param, current_surface->frame_num, &buffering_period_buffer);
838     pic_timing_size = build_packed_sei_pic_timing_buffer(ctx, current_surface->frame_num, &pic_timing_buffer);
839     scalability_info_size = build_packed_sei_scalability_info_buffer(ctx, seq_param, pic_param, current_surface->frame_num, &scalability_info_buffer);
840 
841     if (!buffering_period_buffer &&
842         !pic_timing_buffer &&
843         !scalability_info_buffer) {
844         *sei_buffer = NULL;
845         return 0;
846     }
847 
848     bitstream_start(&nal_bs);
849     nal_start_code_prefix(&nal_bs);
850     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
851 
852     /* Write the SEI buffer */
853     if (buffering_period_buffer) {
854         assert(buffering_period_size);
855 
856         bitstream_put_ui(&nal_bs, 0, 8);                        // last_payload_type_byte: 0
857         bitstream_put_ui(&nal_bs, buffering_period_size, 8);    // last_payload_size_byte
858 
859         for (i = 0; i < buffering_period_size; i++) {
860             bitstream_put_ui(&nal_bs, buffering_period_buffer[i], 8);
861         }
862 
863         free(buffering_period_buffer);
864     }
865 
866     if (pic_timing_buffer) {
867         assert(pic_timing_size);
868 
869         bitstream_put_ui(&nal_bs, 1, 8);                        // last_payload_type_byte: 1
870         bitstream_put_ui(&nal_bs, pic_timing_size, 8);          // last_payload_size_byte
871 
872         for (i = 0; i < pic_timing_size; i++) {
873             bitstream_put_ui(&nal_bs, pic_timing_buffer[i], 8);
874         }
875 
876         free(pic_timing_buffer);
877     }
878 
879     if (scalability_info_buffer) {
880         assert(scalability_info_size);
881 
882         bitstream_put_ui(&nal_bs, 24, 8);                       // last_payload_type_byte: 24
883         bitstream_put_ui(&nal_bs, scalability_info_size, 8);    // last_payload_size_byte
884 
885         for (i = 0; i < scalability_info_size; i++) {
886             bitstream_put_ui(&nal_bs, scalability_info_buffer[i], 8);
887         }
888 
889         free(scalability_info_buffer);
890     }
891 
892     rbsp_trailing_bits(&nal_bs);
893     bitstream_end(&nal_bs);
894 
895     *sei_buffer = (unsigned char *)nal_bs.buffer;
896 
897     return nal_bs.bit_offset;
898 }
899 
900 static void
slice_header(bitstream * bs,VAEncSequenceParameterBufferH264 * sps_param,VAEncPictureParameterBufferH264 * pic_param,VAEncSliceParameterBufferH264 * slice_param,unsigned int reordering_info[2])901 slice_header(bitstream *bs,
902              VAEncSequenceParameterBufferH264 *sps_param,
903              VAEncPictureParameterBufferH264 *pic_param,
904              VAEncSliceParameterBufferH264 *slice_param,
905              unsigned int reordering_info[2])
906 {
907     int first_mb_in_slice = slice_param->macroblock_address;
908     int i;
909 
910     bitstream_put_ue(bs, first_mb_in_slice);        /* first_mb_in_slice: 0 */
911     bitstream_put_ue(bs, slice_param->slice_type);  /* slice_type */
912     bitstream_put_ue(bs, slice_param->pic_parameter_set_id);        /* pic_parameter_set_id: 0 */
913     bitstream_put_ui(bs, pic_param->frame_num, sps_param->seq_fields.bits.log2_max_frame_num_minus4 + 4); /* frame_num */
914 
915     /* frame_mbs_only_flag == 1 */
916     if (!sps_param->seq_fields.bits.frame_mbs_only_flag) {
917         /* FIXME: */
918         assert(0);
919     }
920 
921     if (pic_param->pic_fields.bits.idr_pic_flag)
922         bitstream_put_ue(bs, slice_param->idr_pic_id);      /* idr_pic_id: 0 */
923 
924     if (sps_param->seq_fields.bits.pic_order_cnt_type == 0) {
925         bitstream_put_ui(bs, pic_param->CurrPic.TopFieldOrderCnt, sps_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
926         /* pic_order_present_flag == 0 */
927     } else {
928         /* FIXME: */
929         assert(0);
930     }
931 
932     /* redundant_pic_cnt_present_flag == 0 */
933     /* slice type */
934     if (IS_P_SLICE(slice_param->slice_type)) {
935         bitstream_put_ui(bs, !!((reordering_info[0] >> 16) & 0xFF), 1);     /* num_ref_idx_active_override_flag: */
936 
937         if ((reordering_info[0] >> 16) & 0xFF)
938             bitstream_put_ue(bs, (reordering_info[0] >> 24) & 0xFF);        /* num_ref_idx_l0_active_minus1 */
939 
940         /* ref_pic_list_reordering */
941         if (!(reordering_info[0] & 0x0F))
942             bitstream_put_ui(bs, 0, 1);             /* ref_pic_list_reordering_flag_l0: 0 */
943         else {
944             bitstream_put_ui(bs, 1, 1);             /* ref_pic_list_reordering_flag_l0: 1 */
945             bitstream_put_ue(bs, (reordering_info[0] >> 4) & 0x0F);
946             bitstream_put_ue(bs, (reordering_info[0] >> 8) & 0xFF);
947             bitstream_put_ue(bs, 3);                /* modification_of_pic_nums_idc: 3 */
948         }
949     } else if (IS_B_SLICE(slice_param->slice_type)) {
950         bitstream_put_ui(bs, slice_param->direct_spatial_mv_pred_flag, 1);            /* direct_spatial_mv_pred: 1 */
951 
952         bitstream_put_ui(bs, ((reordering_info[0] >> 16) & 0xFF) || ((reordering_info[1] >> 16) & 0xFF), 1);                /* num_ref_idx_active_override_flag: */
953 
954         if (((reordering_info[0] >> 16) & 0xFF) || ((reordering_info[1] >> 16) & 0xFF)) {
955             bitstream_put_ue(bs, (reordering_info[0] >> 24) & 0xFF);        /* num_ref_idx_l0_active_minus1 */
956             bitstream_put_ue(bs, (reordering_info[1] >> 24) & 0xFF);        /* num_ref_idx_l0_active_minus1 */
957         }
958 
959         /* ref_pic_list_reordering */
960 
961         for (i = 0; i < 2; i++) {
962             if (!(reordering_info[i] & 0x0F))
963                 bitstream_put_ui(bs, 0, 1);             /* ref_pic_list_reordering_flag_l0/l1: 0 */
964             else {
965                 bitstream_put_ui(bs, 1, 1);             /* ref_pic_list_reordering_flag_l0/l1: 1 */
966                 bitstream_put_ue(bs, (reordering_info[i] >> 4) & 0x0F);
967                 bitstream_put_ue(bs, (reordering_info[i] >> 8) & 0xFF);
968                 bitstream_put_ue(bs, 3);                /* modification_of_pic_nums_idc: 3 */
969             }
970         }
971     }
972 
973     if ((pic_param->pic_fields.bits.weighted_pred_flag &&
974          IS_P_SLICE(slice_param->slice_type)) ||
975         ((pic_param->pic_fields.bits.weighted_bipred_idc == 1) &&
976          IS_B_SLICE(slice_param->slice_type))) {
977         /* FIXME: fill weight/offset table */
978         assert(0);
979     }
980 
981     /* dec_ref_pic_marking */
982     if (pic_param->pic_fields.bits.reference_pic_flag) {     /* nal_ref_idc != 0 */
983         unsigned char no_output_of_prior_pics_flag = 0;
984         unsigned char long_term_reference_flag = 0;
985         unsigned char adaptive_ref_pic_marking_mode_flag = 0;
986 
987         if (pic_param->pic_fields.bits.idr_pic_flag) {
988             bitstream_put_ui(bs, no_output_of_prior_pics_flag, 1);            /* no_output_of_prior_pics_flag: 0 */
989             bitstream_put_ui(bs, long_term_reference_flag, 1);            /* long_term_reference_flag: 0 */
990         } else {
991             bitstream_put_ui(bs, adaptive_ref_pic_marking_mode_flag, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
992         }
993     }
994 
995     if (pic_param->pic_fields.bits.entropy_coding_mode_flag &&
996         !IS_I_SLICE(slice_param->slice_type))
997         bitstream_put_ue(bs, slice_param->cabac_init_idc);               /* cabac_init_idc: 0 */
998 
999     bitstream_put_se(bs, slice_param->slice_qp_delta);                   /* slice_qp_delta: 0 */
1000 
1001     /* ignore for SP/SI */
1002 
1003     if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag) {
1004         bitstream_put_ue(bs, slice_param->disable_deblocking_filter_idc);           /* disable_deblocking_filter_idc: 0 */
1005 
1006         if (slice_param->disable_deblocking_filter_idc != 1) {
1007             bitstream_put_se(bs, slice_param->slice_alpha_c0_offset_div2);          /* slice_alpha_c0_offset_div2: 2 */
1008             bitstream_put_se(bs, slice_param->slice_beta_offset_div2);              /* slice_beta_offset_div2: 2 */
1009         }
1010     }
1011 
1012     if (pic_param->pic_fields.bits.entropy_coding_mode_flag) {
1013         bitstream_byte_aligning(bs, 1);
1014     }
1015 }
1016 
1017 static void
nal_header_extension(bitstream * bs,VAEncPictureParameterBufferH264 * pic_param,unsigned int temporal_id)1018 nal_header_extension(bitstream *bs,
1019                      VAEncPictureParameterBufferH264 *pic_param,
1020                      unsigned int temporal_id)
1021 {
1022     int is_idr = !!pic_param->pic_fields.bits.idr_pic_flag;
1023 
1024     /* 3 bytes */
1025     bitstream_put_ui(bs, 1, 1);     /* svc_extension_flag */
1026     bitstream_put_ui(bs, !!is_idr, 1);
1027     bitstream_put_ui(bs, 0, 6);     /* priority_id */
1028     bitstream_put_ui(bs, 1, 1);     /* no_inter_layer_pred_flag */
1029     bitstream_put_ui(bs, 0, 3);     /* dependency_id */
1030     bitstream_put_ui(bs, 0, 4);     /* quality_id */
1031     bitstream_put_ui(bs, temporal_id, 3); /* temporal_id */
1032     bitstream_put_ui(bs, 0, 1);     /* use_ref_base_pic_flag */
1033     bitstream_put_ui(bs, 1, 1);     /* discardable_flag */
1034     bitstream_put_ui(bs, 1, 1);     /* output_flag */
1035     bitstream_put_ui(bs, 3, 2);     /* reserved_three_2bits */
1036 }
1037 
1038 static void
nal_unit_svc_prefix_rbsp(bitstream * bs,int is_ref)1039 nal_unit_svc_prefix_rbsp(bitstream *bs, int is_ref)
1040 {
1041     if (is_ref) {
1042         bitstream_put_ui(bs, 0, 1); /* store_ref_base_pic_flag */
1043         bitstream_put_ui(bs, 0, 1); /* additional_prefix_nal_unit_extension_flag*/
1044     } else {
1045         /* no more rbsp data */
1046     }
1047 
1048     rbsp_trailing_bits(bs);
1049 }
1050 
1051 static int
build_packed_svc_prefix_nal_unit(VAEncPictureParameterBufferH264 * pic_param,unsigned int temporal_id,unsigned char ** nal_unit_buffer)1052 build_packed_svc_prefix_nal_unit(VAEncPictureParameterBufferH264 *pic_param,
1053                                  unsigned int temporal_id,
1054                                  unsigned char **nal_unit_buffer)
1055 {
1056     int is_ref = !!pic_param->pic_fields.bits.reference_pic_flag;
1057     bitstream bs;
1058 
1059     bitstream_start(&bs);
1060     nal_start_code_prefix(&bs);
1061 
1062     nal_header(&bs, is_ref ? NAL_REF_IDC_LOW : NAL_REF_IDC_NONE, NAL_PREFIX);
1063     nal_header_extension(&bs, pic_param, temporal_id);
1064     nal_unit_svc_prefix_rbsp(&bs, is_ref);
1065 
1066     bitstream_end(&bs);
1067     *nal_unit_buffer = (unsigned char *)bs.buffer;
1068 
1069     return bs.bit_offset;
1070 }
1071 
1072 static int
build_packed_slice_header_buffer(struct svcenc_context * ctx,VAEncSequenceParameterBufferH264 * sps_param,VAEncPictureParameterBufferH264 * pic_param,VAEncSliceParameterBufferH264 * slice_param,unsigned int reordering_info[2],unsigned char ** header_buffer)1073 build_packed_slice_header_buffer(struct svcenc_context *ctx,
1074                                  VAEncSequenceParameterBufferH264 *sps_param,
1075                                  VAEncPictureParameterBufferH264 *pic_param,
1076                                  VAEncSliceParameterBufferH264 *slice_param,
1077                                  unsigned int reordering_info[2],
1078                                  unsigned char **header_buffer)
1079 {
1080     bitstream bs;
1081     int is_idr = !!pic_param->pic_fields.bits.idr_pic_flag;
1082     int is_ref = !!pic_param->pic_fields.bits.reference_pic_flag;
1083 
1084     bitstream_start(&bs);
1085     nal_start_code_prefix(&bs);
1086 
1087     if (IS_I_SLICE(slice_param->slice_type)) {
1088         nal_header(&bs, NAL_REF_IDC_HIGH, is_idr ? NAL_IDR : NAL_NON_IDR);
1089     } else if (IS_P_SLICE(slice_param->slice_type)) {
1090         assert(!is_idr);
1091         nal_header(&bs, is_ref ? NAL_REF_IDC_MEDIUM : NAL_REF_IDC_NONE, NAL_NON_IDR);
1092     } else {
1093         assert(IS_B_SLICE(slice_param->slice_type));
1094         assert(!is_idr);
1095         nal_header(&bs, is_ref ? NAL_REF_IDC_LOW : NAL_REF_IDC_NONE, NAL_NON_IDR);
1096     }
1097 
1098     slice_header(&bs, sps_param, pic_param, slice_param, reordering_info);
1099 
1100     bitstream_end(&bs);
1101     *header_buffer = (unsigned char *)bs.buffer;
1102 
1103     return bs.bit_offset;
1104 }
1105 
1106 /* upload thread */
1107 static struct upload_task_t *
upload_task_dequeue(struct svcenc_context * ctx)1108 upload_task_dequeue(struct svcenc_context *ctx)
1109 {
1110     struct upload_task_t *task;
1111 
1112     pthread_mutex_lock(&upload_mutex);
1113 
1114     task = ctx->upload_task_header;
1115 
1116     if (task) {
1117         ctx->upload_task_header = task->next;
1118 
1119         if (!ctx->upload_task_header)
1120             ctx->upload_task_tail = NULL;
1121     }
1122 
1123     pthread_mutex_unlock(&upload_mutex);
1124 
1125     return task;
1126 }
1127 
1128 static int
upload_task_queue(struct svcenc_context * ctx,unsigned int display_order,int surface)1129 upload_task_queue(struct svcenc_context *ctx, unsigned int display_order, int surface)
1130 {
1131     struct upload_task_t *task;
1132 
1133     task = calloc(1, sizeof(struct upload_task_t));
1134     assert(task);
1135     task->display_order = display_order;
1136     task->surface = surface;
1137     task->next = NULL;
1138 
1139     pthread_mutex_lock(&upload_mutex);
1140 
1141     if (!ctx->upload_task_header)
1142         ctx->upload_task_header = task;
1143 
1144     if (ctx->upload_task_tail)
1145         ctx->upload_task_tail->next = task;
1146 
1147     ctx->upload_task_tail = task;
1148     src_surface_status[surface] = SRC_SURFACE_IN_STORAGE;
1149     pthread_cond_signal(&upload_cond);
1150 
1151     pthread_mutex_unlock(&upload_mutex);
1152 
1153     return 0;
1154 }
1155 
1156 static void
upload_task(struct svcenc_context * ctx,unsigned int display_order,int surface)1157 upload_task(struct svcenc_context *ctx, unsigned int display_order, int surface)
1158 {
1159     VAStatus va_status;
1160     VAImage surface_image;
1161     void *surface_p = NULL;
1162     size_t n_items;
1163     unsigned char *y_src, *u_src, *v_src;
1164     unsigned char *y_dst, *u_dst, *v_dst;
1165     int row, col;
1166     int y_size = ctx->width * ctx->height;
1167     int u_size = (ctx->width >> 1) * (ctx->height >> 1);
1168 
1169     int ret = fseek(ctx->ifp, ctx->frame_size * display_order, SEEK_SET);
1170     CHECK_CONDITION(ret == 0);
1171 
1172     do {
1173         n_items = fread(ctx->frame_data_buffer, ctx->frame_size, 1, ctx->ifp);
1174     } while (n_items != 1);
1175 
1176     va_status = vaDeriveImage(ctx->va_dpy, src_surfaces[surface], &surface_image);
1177     CHECK_VASTATUS(va_status, "vaDeriveImage");
1178 
1179     vaMapBuffer(ctx->va_dpy, surface_image.buf, &surface_p);
1180     assert(VA_STATUS_SUCCESS == va_status);
1181 
1182     y_src = ctx->frame_data_buffer;
1183     u_src = ctx->frame_data_buffer + y_size; /* UV offset for NV12 */
1184     v_src = ctx->frame_data_buffer + y_size + u_size;
1185 
1186     y_dst = (unsigned char *)surface_p + surface_image.offsets[0];
1187     u_dst = (unsigned char *)surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
1188     v_dst = (unsigned char *)surface_p + surface_image.offsets[2];
1189 
1190     /* Y plane */
1191     for (row = 0; row < surface_image.height; row++) {
1192         memcpy(y_dst, y_src, surface_image.width);
1193         y_dst += surface_image.pitches[0];
1194         y_src += ctx->width;
1195     }
1196 
1197     if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
1198         for (row = 0; row < surface_image.height / 2; row++) {
1199             for (col = 0; col < surface_image.width / 2; col++) {
1200                 u_dst[col * 2] = u_src[col];
1201                 u_dst[col * 2 + 1] = v_src[col];
1202             }
1203 
1204             u_dst += surface_image.pitches[1];
1205             u_src += (ctx->width / 2);
1206             v_src += (ctx->width / 2);
1207         }
1208     } else {
1209         for (row = 0; row < surface_image.height / 2; row++) {
1210             for (col = 0; col < surface_image.width / 2; col++) {
1211                 u_dst[col] = u_src[col];
1212                 v_dst[col] = v_src[col];
1213             }
1214 
1215             u_dst += surface_image.pitches[1];
1216             v_dst += surface_image.pitches[2];
1217             u_src += (ctx->width / 2);
1218             v_src += (ctx->width / 2);
1219         }
1220     }
1221 
1222     vaUnmapBuffer(ctx->va_dpy, surface_image.buf);
1223     vaDestroyImage(ctx->va_dpy, surface_image.image_id);
1224 
1225     pthread_mutex_lock(&upload_mutex);
1226     src_surface_status[surface] = SRC_SURFACE_IN_ENCODING;
1227     pthread_mutex_unlock(&upload_mutex);
1228 }
1229 
1230 static void *
upload_task_thread(void * data)1231 upload_task_thread(void *data)
1232 {
1233     struct svcenc_context *ctx = (struct svcenc_context *)data;
1234     int num = 0;
1235 
1236     while (1) {
1237         struct upload_task_t *task;
1238 
1239         task = upload_task_dequeue(ctx);
1240         if (!task) {
1241             pthread_mutex_lock(&upload_mutex);
1242             pthread_cond_wait(&upload_cond, &upload_mutex);
1243             pthread_mutex_unlock(&upload_mutex);
1244 
1245             continue;
1246         }
1247 
1248         upload_task(ctx, task->display_order, task->surface);
1249         free(task);
1250 
1251         if (++num >= ctx->num_pictures)
1252             break;
1253     }
1254 
1255     return 0;
1256 }
1257 
1258 /* main thread */
1259 static void
usage(char * program)1260 usage(char *program)
1261 {
1262     fprintf(stderr, "Usage: %s --help\n", program);
1263     fprintf(stderr, "\t--help print this message\n");
1264     fprintf(stderr, "Usage: %s <width> <height> <ifile> <ofile> [options] \n", program);
1265     fprintf(stderr, "\t<width>\t\tThe base picture width\n");
1266     fprintf(stderr, "\t<height>\tThe base picture height\n");
1267     fprintf(stderr, "\t<ifiles>\tThe input YUV I420 file\n");
1268     fprintf(stderr, "\t<ofile>\t\tThe output H.264/SVC file\n\n");
1269     fprintf(stderr, "\tAvailable options:\n");
1270     fprintf(stderr, "\t--gop <value>\t\tGOP size, default is 8\n");
1271     fprintf(stderr, "\t--goptype <value>\tGOP hierarchical type, 0 is P hierarchical GOP, 1 is B hierarchical GOP, default is 0\n");
1272     fprintf(stderr, "\t--brcmode <value>\tBRC mode, 0 is CQP mode, otherwise CBR mode, default mode is CQP\n");
1273     fprintf(stderr, "\t--brclayer<value>\tDisable/Enalbe BRC per temporal layer, default is disable(0)\n");
1274     fprintf(stderr, "\t--bitrate <value>\tbit rate in Kbps(1024 bits). It is available for CBR mode only and default value is 2000\n");
1275 }
1276 
1277 static void
svcenc_exit(struct svcenc_context * ctx,int exit_code)1278 svcenc_exit(struct svcenc_context *ctx, int exit_code)
1279 {
1280     if (ctx->ifp) {
1281         fclose(ctx->ifp);
1282         ctx->ifp = NULL;
1283     }
1284 
1285     if (ctx->ofp) {
1286         fclose(ctx->ofp);
1287         ctx->ofp = NULL;
1288     }
1289 
1290     exit(exit_code);
1291 }
1292 
1293 static void
parse_args(struct svcenc_context * ctx,int argc,char ** argv)1294 parse_args(struct svcenc_context *ctx, int argc, char **argv)
1295 {
1296     int c, tmp;
1297     int option_index = 0;
1298     long file_size;
1299 
1300     static struct option long_options[] = {
1301         {"gop",         required_argument,      0,      'g'},
1302         {"goptype",     required_argument,      0,      't'},
1303         {"bitrate",     required_argument,      0,      'b'},
1304         {"brcmode",     required_argument,      0,      'm'},
1305         {"brclayer",    required_argument,      0,      'l'},
1306         {"help",        no_argument,            0,      'h'},
1307         { NULL,         0,                      NULL,   0 }
1308     };
1309 
1310     va_init_display_args(&argc, argv);
1311 
1312     if ((argc == 2 && strcmp(argv[1], "--help") == 0) ||
1313         (argc < 5))
1314         goto print_usage;
1315 
1316     ctx->width = atoi(argv[1]);
1317     ctx->height = atoi(argv[2]);
1318 
1319     if (ctx->width <= 0 || ctx->height <= 0) {
1320         fprintf(stderr, "<base width> and <base height> must be greater than 0\n");
1321         goto err_exit;
1322     }
1323 
1324     ctx->frame_size = ctx->width * ctx->height * 3 / 2;
1325     ctx->ifp = fopen(argv[3], "rb");
1326 
1327     if (ctx->ifp == NULL) {
1328         fprintf(stderr, "Can't open the input file\n");
1329         goto err_exit;
1330     }
1331 
1332     fseek(ctx->ifp, 0l, SEEK_END);
1333     file_size = ftell(ctx->ifp);
1334 
1335     if ((file_size < ctx->frame_size) ||
1336         (file_size % ctx->frame_size)) {
1337         fprintf(stderr, "The input file size %ld isn't a multiple of the frame size %d\n", file_size, ctx->frame_size);
1338         goto err_exit;
1339     }
1340 
1341     assert(ctx->num_pictures == 0);
1342     ctx->num_pictures = file_size / ctx->frame_size;
1343     fseek(ctx->ifp, 0l, SEEK_SET);
1344 
1345     ctx->ofp = fopen(argv[4], "wb");
1346 
1347     if (ctx->ofp == NULL) {
1348         fprintf(stderr, "Can't create the output file\n");
1349         goto err_exit;
1350     }
1351 
1352     opterr = 0;
1353     optind = 5;
1354     ctx->gop_size = 8;
1355     ctx->gop_type = 0;
1356     ctx->bits_per_kbps = -1;
1357     ctx->rate_control_mode = VA_RC_CQP;
1358     ctx->layer_brc = 0;
1359 
1360     while ((c = getopt_long(argc, argv,
1361                             "",
1362                             long_options,
1363                             &option_index)) != -1) {
1364         switch (c) {
1365         case 'g':
1366             tmp = atoi(optarg);
1367 
1368             if ((tmp & (tmp - 1)) ||
1369                 tmp > 8) {
1370                 fprintf(stderr, "Warning: invalid GOP size\n");
1371                 tmp = 8;
1372             }
1373 
1374             ctx->gop_size = tmp;
1375 
1376             break;
1377 
1378         case 't':
1379             tmp = atoi(optarg);
1380 
1381             ctx->gop_type = !!tmp;
1382 
1383             break;
1384 
1385         case 'b':
1386             tmp = atoi(optarg);
1387 
1388             if (tmp <= 0)
1389                 ctx->bits_per_kbps = -1;
1390             else {
1391                 if (tmp >= 30000)
1392                     tmp = 30000;
1393 
1394                 ctx->bits_per_kbps = tmp;
1395             }
1396 
1397             break;
1398 
1399         case 'm':
1400             tmp = atoi(optarg);
1401 
1402             if (tmp == 0)
1403                 ctx->rate_control_mode = VA_RC_CQP;
1404             else
1405                 ctx->rate_control_mode = VA_RC_CBR;
1406 
1407             break;
1408 
1409         case 'l':
1410             tmp = atoi(optarg);
1411 
1412             ctx->layer_brc = !!tmp;
1413 
1414             break;
1415 
1416         case '?':
1417             fprintf(stderr, "Error: unkown command options\n");
1418 
1419         case 'h':
1420             goto print_usage;
1421         }
1422     }
1423 
1424     ctx->num_pictures = ((ctx->num_pictures - 1) & ~(ctx->gop_size - 1)) + 1;
1425 
1426     if (ctx->rate_control_mode == VA_RC_CQP)
1427         ctx->bits_per_kbps = -1;
1428     else {
1429         if (ctx->bits_per_kbps == -1)
1430             ctx->bits_per_kbps = 2000;
1431     }
1432 
1433     return;
1434 
1435 print_usage:
1436     usage(argv[0]);
1437 err_exit:
1438     svcenc_exit(ctx, 1);
1439 }
1440 
1441 void
svcenc_update_ref_frames(struct svcenc_context * ctx,svcenc_surface * current_surface)1442 svcenc_update_ref_frames(struct svcenc_context *ctx, svcenc_surface *current_surface)
1443 {
1444     int i;
1445 
1446     if (!current_surface->is_ref)
1447         return;
1448 
1449     if (current_surface->is_idr)
1450         ctx->num_ref_frames = 1;
1451     else
1452         ctx->num_ref_frames++;
1453 
1454     if (ctx->num_ref_frames > ctx->max_num_ref_frames)
1455         ctx->num_ref_frames = ctx->max_num_ref_frames;
1456 
1457     for (i = ctx->num_ref_frames - 1; i > 0; i--)
1458         ref_frames[i] =  ref_frames[i - 1];
1459 
1460     ref_frames[0] = *current_surface;
1461 }
1462 
1463 static int
svcenc_coding_order_to_display_order(struct svcenc_context * ctx,int coding_order)1464 svcenc_coding_order_to_display_order(struct svcenc_context *ctx, int coding_order)
1465 {
1466     int n, m;
1467     int level;
1468 
1469     assert(coding_order > 0);
1470 
1471     n = (coding_order - 1) / ctx->gop_size;
1472     m = (coding_order - 1) % ctx->gop_size;
1473     level = ctx->hierarchical_levels - temporal_ids_in_bgop[m] - 1;
1474 
1475     return n * ctx->gop_size + gop_factors_in_bgop[m] * (int)pow(2.00, level);
1476 }
1477 
1478 static void
update_next_picture_info(struct svcenc_context * ctx)1479 update_next_picture_info(struct svcenc_context *ctx)
1480 {
1481     svcenc_surface *current_surface = NULL;
1482     svcenc_surface next_surface;
1483     int current_frame_num;
1484 
1485     current_surface = &ctx->next_svcenc_surface;
1486     current_frame_num = current_surface->frame_num;
1487 
1488     next_surface.coding_order = current_surface->coding_order + 1;
1489     next_surface.display_order = svcenc_coding_order_to_display_order(ctx, next_surface.coding_order);
1490     next_surface.slot_in_surfaces = (current_surface->slot_in_surfaces + 1) % NUM_SURFACES;
1491     next_surface.temporal_id = temporal_ids_in_bgop[current_surface->coding_order % ctx->gop_size];
1492     next_surface.is_ref = (next_surface.temporal_id != ctx->hierarchical_levels - 1);
1493 
1494     if (next_surface.temporal_id == 0) {
1495         if (!(next_surface.display_order % ctx->intra_period))
1496             next_surface.picture_type = VAEncPictureTypeIntra;
1497         else
1498             next_surface.picture_type = VAEncPictureTypePredictive;
1499     } else
1500         next_surface.picture_type = VAEncPictureTypeBidirectional;
1501 
1502     if (current_surface->temporal_id == ctx->hierarchical_levels - 1)
1503         next_surface.frame_num = current_frame_num;
1504     else
1505         next_surface.frame_num = current_frame_num + 1;
1506 
1507     next_surface.is_intra = (next_surface.picture_type == VAEncPictureTypeIntra);
1508     next_surface.is_idr = 0;
1509     next_surface.rec_surface = rec_surfaces[next_surface.slot_in_surfaces];
1510     next_surface.poc = next_surface.display_order;
1511 
1512     if (next_surface.is_idr)
1513         next_surface.frame_num = 0;
1514 
1515     *current_surface = next_surface;
1516 }
1517 
1518 static int
svcenc_coding_order_to_level_pgop(struct svcenc_context * ctx,int coding_order)1519 svcenc_coding_order_to_level_pgop(struct svcenc_context *ctx, int coding_order)
1520 {
1521     int m;
1522     int level;
1523 
1524     assert(coding_order > 0);
1525 
1526     m = coding_order % ctx->gop_size;
1527 
1528     if (m == 0)
1529         return 0;
1530 
1531     level = ctx->hierarchical_levels - temporal_ids_in_pgop[m - 1];
1532 
1533     assert(level > 0 && level < 5);
1534 
1535     return level;
1536 }
1537 
1538 static void
update_next_picture_info_pgop(struct svcenc_context * ctx)1539 update_next_picture_info_pgop(struct svcenc_context *ctx)
1540 {
1541     svcenc_surface *current_surface = NULL;
1542     svcenc_surface next_surface;
1543     int current_frame_num;
1544 
1545     current_surface = &ctx->next_svcenc_surface;
1546     current_frame_num = current_surface->frame_num;
1547 
1548     next_surface.coding_order = current_surface->coding_order + 1;
1549     next_surface.display_order = next_surface.coding_order;
1550     next_surface.slot_in_surfaces = (current_surface->slot_in_surfaces + 1) % NUM_SURFACES;
1551     next_surface.temporal_id = svcenc_coding_order_to_level_pgop(ctx, next_surface.coding_order);
1552     next_surface.is_ref = (next_surface.temporal_id != ctx->hierarchical_levels - 1);
1553 
1554     if (next_surface.temporal_id == 0) {
1555         if (!(next_surface.display_order % ctx->intra_period))
1556             next_surface.picture_type = VAEncPictureTypeIntra;
1557         else
1558             next_surface.picture_type = VAEncPictureTypePredictive;
1559     } else {
1560         next_surface.picture_type = VAEncPictureTypePredictive;
1561     }
1562 
1563     next_surface.frame_num = current_frame_num + 1;
1564     next_surface.is_intra = (next_surface.picture_type == VAEncPictureTypeIntra);
1565     next_surface.is_idr = !(next_surface.display_order % ctx->intra_idr_period);
1566     next_surface.rec_surface = rec_surfaces[next_surface.slot_in_surfaces];
1567     next_surface.poc = next_surface.display_order % ctx->intra_idr_period;
1568 
1569     if (next_surface.is_idr) {
1570         next_surface.frame_num = 0;
1571         assert(next_surface.poc == 0);
1572     }
1573 
1574     *current_surface = next_surface;
1575 }
1576 
1577 static int
svcenc_seq_parameter_set_id(struct svcenc_context * ctx,svcenc_surface * current_surface)1578 svcenc_seq_parameter_set_id(struct svcenc_context *ctx,
1579                             svcenc_surface *current_surface)
1580 {
1581     return 0;
1582 }
1583 
1584 static int
svcenc_pic_parameter_set_id(struct svcenc_context * ctx,svcenc_surface * current_surface)1585 svcenc_pic_parameter_set_id(struct svcenc_context *ctx,
1586                             svcenc_surface *current_surface)
1587 {
1588     return 0;
1589 }
1590 
1591 void
svcenc_update_sequence_parameter_buffer(struct svcenc_context * ctx,svcenc_surface * current_surface)1592 svcenc_update_sequence_parameter_buffer(struct svcenc_context *ctx,
1593                                         svcenc_surface *current_surface)
1594 {
1595     VAEncSequenceParameterBufferH264 *seq_param = &ctx->seq_param;
1596     VAStatus va_status;
1597     int width_in_mbs = (ctx->width + 15) / 16;
1598     int height_in_mbs = (ctx->height + 15) / 16;
1599     int frame_cropping_flag = 0;
1600     int frame_crop_bottom_offset = 0;
1601 
1602     memset(seq_param, 0, sizeof(*seq_param));
1603     seq_param->seq_parameter_set_id = svcenc_seq_parameter_set_id(ctx, current_surface);
1604     seq_param->level_idc = 41;
1605     seq_param->intra_period = ctx->intra_period;
1606     seq_param->ip_period = ctx->ip_period;
1607     seq_param->intra_idr_period = ctx->intra_idr_period;
1608     seq_param->max_num_ref_frames = ctx->max_num_ref_frames;
1609     seq_param->picture_width_in_mbs = width_in_mbs;
1610     seq_param->picture_height_in_mbs = height_in_mbs;
1611     seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1612 
1613     if (ctx->bits_per_kbps > 0)
1614         seq_param->bits_per_second = 1024 * ctx->bits_per_kbps;
1615     else
1616         seq_param->bits_per_second = 0;
1617 
1618     seq_param->time_scale = ctx->framerate_per_100s * 2;
1619     seq_param->num_units_in_tick = 100;
1620 
1621     if (height_in_mbs * 16 - ctx->height) {
1622         frame_cropping_flag = 1;
1623         frame_crop_bottom_offset =
1624             (height_in_mbs * 16 - ctx->height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
1625     }
1626 
1627     seq_param->frame_cropping_flag = frame_cropping_flag;
1628     seq_param->frame_crop_left_offset = 0;
1629     seq_param->frame_crop_right_offset = 0;
1630     seq_param->frame_crop_top_offset = 0;
1631     seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1632 
1633     seq_param->seq_fields.bits.pic_order_cnt_type = 0;
1634 
1635     if ((ctx->profile_idc == PROFILE_IDC_SCALABLE_HIGH &&
1636          ctx->constraint_set_flag & (1 << 3)) ||
1637         (ctx->profile_idc == PROFILE_IDC_SCALABLE_BASELINE &&
1638          ctx->constraint_set_flag & (1 << 5)))
1639         seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
1640     else
1641         seq_param->seq_fields.bits.direct_8x8_inference_flag = 1;
1642 
1643     seq_param->seq_fields.bits.log2_max_frame_num_minus4 = 10;
1644     seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 10;
1645 
1646     if (ctx->bits_per_kbps > 0)
1647         seq_param->vui_parameters_present_flag = 1; //HRD info located in vui
1648     else
1649         seq_param->vui_parameters_present_flag = 0;
1650 
1651     va_status = vaCreateBuffer(ctx->va_dpy,
1652                                ctx->context_id,
1653                                VAEncSequenceParameterBufferType,
1654                                sizeof(*seq_param),
1655                                1,
1656                                seq_param,
1657                                &ctx->seq_param_buf_id);
1658     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1659 }
1660 
1661 void
svcenc_update_picture_parameter_buffer(struct svcenc_context * ctx,svcenc_surface * current_surface)1662 svcenc_update_picture_parameter_buffer(struct svcenc_context *ctx,
1663                                        svcenc_surface *current_surface)
1664 {
1665     VAEncPictureParameterBufferH264 *pic_param;
1666     VAStatus va_status;
1667     int i;
1668 
1669     /* Allocate the new coded buffer */
1670     va_status = vaCreateBuffer(ctx->va_dpy,
1671                                ctx->context_id,
1672                                VAEncCodedBufferType,
1673                                ctx->frame_size,
1674                                1,
1675                                NULL,
1676                                &ctx->codedbuf_buf_id);
1677     assert(ctx->codedbuf_buf_id != VA_INVALID_ID);
1678     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1679 
1680     /* H.264 picture parameter */
1681     pic_param = &ctx->pic_param;
1682     memset(pic_param, 0, sizeof(*pic_param));
1683 
1684     pic_param->seq_parameter_set_id = svcenc_seq_parameter_set_id(ctx, current_surface);
1685     pic_param->pic_parameter_set_id = svcenc_pic_parameter_set_id(ctx, current_surface);
1686     pic_param->last_picture = 0;
1687     pic_param->pic_init_qp = 34;
1688 
1689     pic_param->num_ref_idx_l0_active_minus1 = ctx->hierarchical_levels - 1;
1690     pic_param->num_ref_idx_l1_active_minus1 = ctx->hierarchical_levels - 1;
1691 
1692     pic_param->coded_buf = ctx->codedbuf_buf_id;
1693     pic_param->frame_num = current_surface->frame_num;
1694 
1695     pic_param->CurrPic.picture_id = current_surface->rec_surface;
1696     pic_param->CurrPic.TopFieldOrderCnt = current_surface->poc * 2;
1697     pic_param->CurrPic.BottomFieldOrderCnt = pic_param->CurrPic.TopFieldOrderCnt;
1698     pic_param->CurrPic.frame_idx = current_surface->frame_num;
1699     pic_param->CurrPic.flags = 0; /* frame */
1700 
1701     for (i = 0; i < ctx->num_ref_frames; i++) {
1702         assert(pic_param->CurrPic.picture_id != ref_frames[i].rec_surface);
1703 
1704         pic_param->ReferenceFrames[i].picture_id = ref_frames[i].rec_surface;
1705         pic_param->ReferenceFrames[i].TopFieldOrderCnt = ref_frames[i].poc * 2;
1706         pic_param->ReferenceFrames[i].BottomFieldOrderCnt = pic_param->ReferenceFrames[i].TopFieldOrderCnt;
1707         pic_param->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
1708     }
1709 
1710     for (; i < 16; i++) {
1711         pic_param->ReferenceFrames[i].picture_id = VA_INVALID_ID;
1712         pic_param->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
1713     }
1714 
1715     pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CAVLC;
1716     pic_param->pic_fields.bits.weighted_pred_flag = 0;
1717     pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1718     pic_param->pic_fields.bits.idr_pic_flag = !!current_surface->is_idr;
1719     pic_param->pic_fields.bits.reference_pic_flag = !!current_surface->is_ref;
1720     pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1721 
1722     if (ctx->profile_idc == PROFILE_IDC_BASELINE ||
1723         ctx->profile_idc == PROFILE_IDC_MAIN ||
1724         ctx->profile_idc == PROFILE_IDC_SCALABLE_BASELINE)
1725         pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1726     else
1727         pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1728 
1729     /* Allocate the new picture parameter buffer */
1730     va_status = vaCreateBuffer(ctx->va_dpy,
1731                                ctx->context_id,
1732                                VAEncPictureParameterBufferType,
1733                                sizeof(*pic_param),
1734                                1,
1735                                pic_param,
1736                                &ctx->pic_param_buf_id);
1737     assert(ctx->pic_param_buf_id != VA_INVALID_ID);
1738     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1739 }
1740 
1741 #define partition(ref, field, key, ascending)   \
1742     while (i <= j) {                            \
1743         if (ascending) {                        \
1744             while (ref[i].field < key)          \
1745                 i++;                            \
1746             while (ref[j].field > key)          \
1747                 j--;                            \
1748         } else {                                \
1749             while (ref[i].field > key)          \
1750                 i++;                            \
1751             while (ref[j].field < key)          \
1752                 j--;                            \
1753         }                                       \
1754         if (i <= j) {                           \
1755             tmp = ref[i];                       \
1756             ref[i] = ref[j];                    \
1757             ref[j] = tmp;                       \
1758             i++;                                \
1759             j--;                                \
1760         }                                       \
1761     }                                           \
1762 
1763 static void
sort_one(svcenc_surface ref[],int left,int right,int ascending,int is_frame_num)1764 sort_one(svcenc_surface ref[],
1765          int left, int right,
1766          int ascending, int is_frame_num)
1767 {
1768     int i = left, j = right;
1769     int key;
1770     svcenc_surface tmp;
1771 
1772     if (is_frame_num) {
1773         key = ref[(left + right) / 2].frame_num;
1774         partition(ref, frame_num, key, ascending);
1775     } else {
1776         key = ref[(left + right) / 2].display_order;
1777         partition(ref, display_order, (signed int)key, ascending);
1778     }
1779 
1780     /* recursion */
1781     if (left < j)
1782         sort_one(ref, left, j, ascending, is_frame_num);
1783 
1784     if (i < right)
1785         sort_one(ref, i, right, ascending, is_frame_num);
1786 }
1787 
1788 static void
sort_two(svcenc_surface ref[],int left,int right,int key,int is_frame_num,int partition_ascending,int list0_ascending,int list1_ascending)1789 sort_two(svcenc_surface ref[],
1790          int left, int right,
1791          int key, int is_frame_num,
1792          int partition_ascending,
1793          int list0_ascending, int list1_ascending)
1794 {
1795     int i = left, j = right;
1796     svcenc_surface tmp;
1797 
1798     if (is_frame_num) {
1799         partition(ref, frame_num, key, partition_ascending);
1800     } else {
1801         partition(ref, display_order, key, partition_ascending);
1802     }
1803 
1804     sort_one(ref, left, i - 1, list0_ascending, is_frame_num);
1805     sort_one(ref, j + 1, right, list1_ascending, is_frame_num);
1806 }
1807 
1808 static void
svcenc_update_ref_lists(struct svcenc_context * ctx,svcenc_surface * current_surface)1809 svcenc_update_ref_lists(struct svcenc_context *ctx,
1810                         svcenc_surface *current_surface)
1811 {
1812     if (current_surface->picture_type == VAEncPictureTypePredictive) {
1813         memcpy(ref_list0, ref_frames, ctx->num_ref_frames * sizeof(svcenc_surface));
1814         sort_one(ref_list0, 0, ctx->num_ref_frames - 1, 0, 1);
1815     } else if (current_surface->picture_type == VAEncPictureTypeBidirectional) {
1816         memcpy(ref_list0, ref_frames, ctx->num_ref_frames * sizeof(svcenc_surface));
1817         sort_two(ref_list0,
1818                  0, ctx->num_ref_frames - 1,
1819                  current_surface->display_order, 0,
1820                  1,
1821                  0, 1);
1822         memcpy(ref_list1, ref_frames, ctx->num_ref_frames * sizeof(svcenc_surface));
1823         sort_two(ref_list1,
1824                  0, ctx->num_ref_frames - 1,
1825                  current_surface->display_order, 0,
1826                  0,
1827                  1, 0);
1828     }
1829 }
1830 
1831 static int
avc_temporal_find_surface(VAPictureH264 * curr_pic,VAPictureH264 * ref_list,int num_pictures,int dir)1832 avc_temporal_find_surface(VAPictureH264 *curr_pic,
1833                           VAPictureH264 *ref_list,
1834                           int num_pictures,
1835                           int dir)
1836 {
1837     int i, found = -1, min = 0x7FFFFFFF;
1838 
1839     for (i = 0; i < num_pictures; i++) {
1840         int tmp;
1841 
1842         if ((ref_list[i].flags & VA_PICTURE_H264_INVALID) ||
1843             (ref_list[i].picture_id == VA_INVALID_SURFACE))
1844             break;
1845 
1846         tmp = curr_pic->TopFieldOrderCnt - ref_list[i].TopFieldOrderCnt;
1847 
1848         if (dir)
1849             tmp = -tmp;
1850 
1851         if (tmp > 0 && tmp < min) {
1852             min = tmp;
1853             found = i;
1854         }
1855     }
1856 
1857     assert(found != -1);
1858 
1859     return found;
1860 }
1861 
1862 static int
avc_temporal_find_surface_pgop(svcenc_surface * curr_pic,svcenc_surface * ref_list,int num_pictures)1863 avc_temporal_find_surface_pgop(svcenc_surface *curr_pic,
1864                                svcenc_surface *ref_list,
1865                                int num_pictures)
1866 {
1867     int i, found = -1, min = 0x7FFFFFFF;
1868 
1869     for (i = 0; i < num_pictures; i++) {
1870         int tmp;
1871 
1872         if (ref_list[i].rec_surface == VA_INVALID_SURFACE)
1873             break;
1874 
1875         if (curr_pic->temporal_id < ref_list[i].temporal_id)
1876             continue;
1877 
1878         tmp = curr_pic->display_order - ref_list[i].display_order;
1879 
1880         if (tmp > 0 && tmp < min) {
1881             min = tmp;
1882             found = i;
1883         }
1884     }
1885 
1886     assert(found != -1);
1887 
1888     return found;
1889 }
1890 
1891 void
svcenc_update_slice_parameter_buffer(struct svcenc_context * ctx,svcenc_surface * current_surface)1892 svcenc_update_slice_parameter_buffer(struct svcenc_context *ctx,
1893                                      svcenc_surface *current_surface)
1894 {
1895     VAEncPictureParameterBufferH264 *pic_param = &ctx->pic_param;
1896     VAEncSliceParameterBufferH264 *slice_param;
1897     VAStatus va_status;
1898     int i, width_in_mbs, height_in_mbs;
1899     int slice_type;
1900     int num_ref_idx_active_override_flag = 0, num_ref_l0 = 1, num_ref_l1 = 1;
1901     VAPictureH264 RefPicList0[32];
1902     VAPictureH264 RefPicList1[32];
1903     VAPictureH264 *curr_pic;
1904     int ref_idx;
1905 
1906     memset(RefPicList0, 0, sizeof(RefPicList0));
1907     memset(RefPicList1, 0, sizeof(RefPicList1));
1908 
1909     svcenc_update_ref_lists(ctx, current_surface);
1910 
1911     switch (current_surface->picture_type) {
1912     case VAEncPictureTypeBidirectional:
1913         slice_type = SLICE_TYPE_B;
1914         break;
1915 
1916     case VAEncPictureTypePredictive:
1917         slice_type = SLICE_TYPE_P;
1918         break;
1919 
1920     case VAEncPictureTypeIntra:
1921     default:
1922         slice_type = SLICE_TYPE_I;
1923         break;
1924     }
1925 
1926     width_in_mbs = (ctx->width + 15) / 16;
1927     height_in_mbs = (ctx->height + 15) / 16;
1928 
1929     // Slice level
1930     i = 0;
1931     slice_param = &ctx->slice_param[i];
1932     memset(slice_param, 0, sizeof(*slice_param));
1933 
1934     slice_param->macroblock_address = 0;
1935     slice_param->num_macroblocks = height_in_mbs * width_in_mbs;
1936     slice_param->pic_parameter_set_id = svcenc_pic_parameter_set_id(ctx, current_surface);
1937     slice_param->slice_type = slice_type;
1938 
1939     slice_param->direct_spatial_mv_pred_flag = 1; /*
1940                                                    * It is required for the slice layer extension and the base
1941                                                    * layer bitstream
1942                                                    * See G.7.4.3 j), G.10.1.2 a), G.10.1.2.1 a)
1943                                                    */
1944     slice_param->num_ref_idx_active_override_flag = 0;
1945     slice_param->num_ref_idx_l0_active_minus1 = 0;
1946     slice_param->num_ref_idx_l1_active_minus1 = 0;
1947     slice_param->cabac_init_idc = 0;
1948     slice_param->slice_qp_delta = 0;
1949     slice_param->disable_deblocking_filter_idc = 0;
1950     slice_param->slice_alpha_c0_offset_div2 = 2;
1951     slice_param->slice_beta_offset_div2 = 2;
1952     slice_param->idr_pic_id = 0;
1953 
1954     ctx->reordering_info[0] = ctx->reordering_info[1] = 0;
1955 
1956     /* FIXME: fill other fields */
1957     if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
1958         int j;
1959         num_ref_l0 = MIN((pic_param->num_ref_idx_l0_active_minus1 + 1), ctx->num_ref_frames);
1960 
1961         for (j = 0; j < num_ref_l0; j++) {
1962             RefPicList0[j].picture_id = ref_list0[j].rec_surface;
1963             RefPicList0[j].TopFieldOrderCnt = ref_list0[j].poc * 2;
1964             RefPicList0[j].BottomFieldOrderCnt = RefPicList0[j].TopFieldOrderCnt;
1965             RefPicList0[j].frame_idx = ref_list0[j].frame_num;
1966             RefPicList0[j].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
1967         }
1968 
1969         for (; j < 32; j++) {
1970             RefPicList0[j].picture_id = VA_INVALID_SURFACE;
1971             RefPicList0[j].flags = VA_PICTURE_H264_INVALID;
1972         }
1973 
1974         if (num_ref_l0 != pic_param->num_ref_idx_l0_active_minus1 + 1)
1975             num_ref_idx_active_override_flag = 1;
1976     }
1977 
1978     if (slice_type == SLICE_TYPE_B) {
1979         int j;
1980         num_ref_l1 = MIN((pic_param->num_ref_idx_l1_active_minus1 + 1), ctx->num_ref_frames);
1981 
1982         for (j = 0; j < num_ref_l1; j++) {
1983             RefPicList1[j].picture_id = ref_list1[j].rec_surface;
1984             RefPicList1[j].TopFieldOrderCnt = ref_list1[j].poc * 2;
1985             RefPicList1[j].BottomFieldOrderCnt = RefPicList1[j].TopFieldOrderCnt;
1986             RefPicList1[j].frame_idx = ref_list1[j].frame_num;
1987             RefPicList1[j].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
1988         }
1989 
1990         for (; j < 32; j++) {
1991             RefPicList1[j].picture_id = VA_INVALID_SURFACE;
1992             RefPicList1[j].flags = VA_PICTURE_H264_INVALID;
1993         }
1994 
1995         if (num_ref_l1 != pic_param->num_ref_idx_l1_active_minus1 + 1)
1996             num_ref_idx_active_override_flag = 1;
1997     }
1998 
1999     if (num_ref_l0 != 1 || num_ref_l1 != 1) {
2000         curr_pic = &pic_param->CurrPic;
2001 
2002         /* select the reference frame in temporal space */
2003         if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
2004             if (ctx->gop_type == 1)
2005                 ref_idx = avc_temporal_find_surface(curr_pic, RefPicList0, num_ref_l0, 0);
2006             else
2007                 ref_idx = avc_temporal_find_surface_pgop(current_surface, ref_list0, num_ref_l0);
2008 
2009             if (ref_idx != 0) {
2010                 ctx->reordering_info[0] |= (1 << 0);
2011 
2012                 if (curr_pic->frame_idx > RefPicList0[ref_idx].frame_idx) {
2013                     ctx->reordering_info[0] |= (0 << 4);
2014                     ctx->reordering_info[0] |= ((curr_pic->frame_idx - RefPicList0[ref_idx].frame_idx - 1) << 8);
2015                 } else {
2016                     ctx->reordering_info[0] |= (1 << 4);
2017                     ctx->reordering_info[0] |= ((RefPicList0[ref_idx].frame_idx - curr_pic->frame_idx - 1) << 8);
2018                 }
2019             }
2020 
2021             slice_param->RefPicList0[0] = RefPicList0[ref_idx];
2022         }
2023 
2024         if (slice_type == SLICE_TYPE_B) {
2025             assert(ctx->gop_type == 1);
2026             ref_idx = avc_temporal_find_surface(curr_pic, RefPicList1, num_ref_l1, 1);
2027 
2028             if (ref_idx != 0) {
2029                 ctx->reordering_info[1] |= (1 << 0);
2030 
2031                 if (curr_pic->frame_idx > RefPicList1[ref_idx].frame_idx) {
2032                     ctx->reordering_info[1] |= (0 << 4);
2033                     ctx->reordering_info[1] |= ((curr_pic->frame_idx - RefPicList1[ref_idx].frame_idx - 1) << 8);
2034                 } else {
2035                     ctx->reordering_info[1] |= (1 << 4);
2036                     ctx->reordering_info[1] |= ((RefPicList1[ref_idx].frame_idx - curr_pic->frame_idx - 1) << 8);
2037                 }
2038             }
2039 
2040             slice_param->RefPicList1[0] = RefPicList1[ref_idx];
2041         }
2042 
2043         slice_param->num_ref_idx_active_override_flag = 1;
2044         slice_param->num_ref_idx_l0_active_minus1 = 0;
2045         slice_param->num_ref_idx_l1_active_minus1 = 0;
2046         ctx->reordering_info[0] |= ((1 << 16) | (0 << 24));
2047         ctx->reordering_info[1] |= ((1 << 16) | (0 << 24));
2048     } else {
2049         if (num_ref_idx_active_override_flag == 1) {
2050             slice_param->num_ref_idx_active_override_flag = 1;
2051             slice_param->num_ref_idx_l0_active_minus1 = 0;
2052             slice_param->num_ref_idx_l1_active_minus1 = 0;
2053             ctx->reordering_info[0] |= ((1 << 16) | (0 << 24));
2054             ctx->reordering_info[1] |= ((1 << 16) | (0 << 24));
2055         }
2056 
2057         if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
2058             slice_param->RefPicList0[0] = RefPicList0[0];
2059         }
2060 
2061         if (slice_type == SLICE_TYPE_B) {
2062             slice_param->RefPicList1[0] = RefPicList1[0];
2063         }
2064     }
2065 
2066     va_status = vaCreateBuffer(ctx->va_dpy,
2067                                ctx->context_id,
2068                                VAEncSliceParameterBufferType,
2069                                sizeof(*slice_param),
2070                                1,
2071                                slice_param,
2072                                &ctx->slice_param_buf_id[i]);
2073     CHECK_VASTATUS(va_status, "vaCreateBuffer");;
2074 
2075     ctx->num_slices = ++i;
2076 }
2077 
2078 void
svcenc_update_misc_parameter_buffer(struct svcenc_context * ctx,svcenc_surface * current_surface)2079 svcenc_update_misc_parameter_buffer(struct svcenc_context *ctx, svcenc_surface *current_surface)
2080 {
2081     VAStatus va_status;
2082     VAEncMiscParameterBuffer *misc_param;
2083     VAEncMiscParameterTemporalLayerStructure *misc_layer_structure_param;
2084     VAEncMiscParameterRateControl *misc_ratecontrol_param;
2085     VAEncMiscParameterFrameRate *misc_framerate_param;
2086     VAEncMiscParameterHRD *misc_hrd_param;
2087 
2088     if (current_surface->frame_num != 0)
2089         return;
2090 
2091     if (ctx->rate_control_mode & VA_RC_CQP)
2092         return;
2093 
2094     assert(ctx->bits_per_kbps > 0);
2095 
2096     if (!ctx->layer_brc) {
2097         va_status = vaCreateBuffer(ctx->va_dpy,
2098                                    ctx->context_id,
2099                                    VAEncMiscParameterBufferType,
2100                                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
2101                                    1,
2102                                    NULL,
2103                                    &ctx->misc_parameter_ratecontrol_buf_id[0]);
2104         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2105 
2106         vaMapBuffer(ctx->va_dpy,
2107                     ctx->misc_parameter_ratecontrol_buf_id[0],
2108                     (void **)&misc_param);
2109 
2110         misc_param->type = VAEncMiscParameterTypeRateControl;
2111         misc_ratecontrol_param = (VAEncMiscParameterRateControl *)misc_param->data;
2112 
2113         misc_ratecontrol_param->bits_per_second = 1024 * ctx->bits_per_kbps;
2114 
2115         vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_ratecontrol_buf_id[0]);
2116 
2117         va_status = vaCreateBuffer(ctx->va_dpy,
2118                                    ctx->context_id,
2119                                    VAEncMiscParameterBufferType,
2120                                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterFrameRate),
2121                                    1,
2122                                    NULL,
2123                                    &ctx->misc_parameter_framerate_buf_id[0]);
2124         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2125 
2126         vaMapBuffer(ctx->va_dpy,
2127                     ctx->misc_parameter_framerate_buf_id[0],
2128                     (void **)&misc_param);
2129 
2130         misc_param->type = VAEncMiscParameterTypeFrameRate;
2131         misc_framerate_param = (VAEncMiscParameterFrameRate *)misc_param->data;
2132         misc_framerate_param->framerate = ((100 << 16) | ctx->framerate_per_100s);
2133 
2134         misc_ratecontrol_param->bits_per_second = 1024 * ctx->bits_per_kbps;
2135 
2136         vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_ratecontrol_buf_id[0]);
2137 
2138         va_status = vaCreateBuffer(ctx->va_dpy,
2139                                    ctx->context_id,
2140                                    VAEncMiscParameterBufferType,
2141                                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
2142                                    1,
2143                                    NULL,
2144                                    &ctx->misc_parameter_hrd_buf_id);
2145         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2146 
2147         vaMapBuffer(ctx->va_dpy,
2148                     ctx->misc_parameter_hrd_buf_id,
2149                     (void **)&misc_param);
2150 
2151         misc_param->type = VAEncMiscParameterTypeHRD;
2152         misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
2153 
2154         misc_hrd_param->initial_buffer_fullness = ctx->bits_per_kbps * 1024 * 4;
2155         misc_hrd_param->buffer_size = ctx->bits_per_kbps * 1024 * 8;
2156 
2157         vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_hrd_buf_id);
2158     } else {
2159         int i, j, nlayers = 0;
2160 
2161         va_status = vaCreateBuffer(ctx->va_dpy,
2162                                    ctx->context_id,
2163                                    VAEncMiscParameterBufferType,
2164                                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterTemporalLayerStructure),
2165                                    1,
2166                                    NULL,
2167                                    &ctx->misc_parameter_layer_structure_buf_id);
2168         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2169 
2170         vaMapBuffer(ctx->va_dpy,
2171                     ctx->misc_parameter_layer_structure_buf_id,
2172                     (void **)&misc_param);
2173 
2174         misc_param->type = VAEncMiscParameterTypeTemporalLayerStructure;
2175         misc_layer_structure_param = (VAEncMiscParameterTemporalLayerStructure *)misc_param->data;
2176 
2177         misc_layer_structure_param->number_of_layers = ctx->hierarchical_levels;
2178         misc_layer_structure_param->periodicity = ctx->gop_size;
2179 
2180         for (i = 0; i < ctx->gop_size; i++) {
2181             if (ctx->gop_type == 1) { // B
2182                 misc_layer_structure_param->layer_id[i] = temporal_ids_in_bgop[i];
2183             } else {
2184                 misc_layer_structure_param->layer_id[i] = svcenc_coding_order_to_level_pgop(ctx, i + 1);
2185             }
2186         }
2187 
2188         vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_layer_structure_buf_id);
2189 
2190         for (i = 1; i <= ctx->hierarchical_levels; i++) {
2191             nlayers += i;
2192         }
2193 
2194         for (i = 0; i < ctx->hierarchical_levels; i++) {
2195             int framerate_per_100s = frame_rates[i] * 100;
2196             int numerator = 0;
2197 
2198             for (j = 0; j < ctx->gop_size; j++) {
2199                 if (misc_layer_structure_param->layer_id[j] <= i)
2200                     numerator++;
2201             }
2202 
2203             va_status = vaCreateBuffer(ctx->va_dpy,
2204                                        ctx->context_id,
2205                                        VAEncMiscParameterBufferType,
2206                                        sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
2207                                        1,
2208                                        NULL,
2209                                        &ctx->misc_parameter_ratecontrol_buf_id[i]);
2210             CHECK_VASTATUS(va_status, "vaCreateBuffer");
2211 
2212             vaMapBuffer(ctx->va_dpy,
2213                         ctx->misc_parameter_ratecontrol_buf_id[i],
2214                         (void **)&misc_param);
2215 
2216             misc_param->type = VAEncMiscParameterTypeRateControl;
2217             misc_ratecontrol_param = (VAEncMiscParameterRateControl *)misc_param->data;
2218             misc_ratecontrol_param->bits_per_second = 1024 * ctx->bits_per_kbps * ((float)numerator / ctx->gop_size);
2219             misc_ratecontrol_param->rc_flags.bits.temporal_id = i;
2220 
2221             vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_ratecontrol_buf_id[i]);
2222 
2223             va_status = vaCreateBuffer(ctx->va_dpy,
2224                                        ctx->context_id,
2225                                        VAEncMiscParameterBufferType,
2226                                        sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterFrameRate),
2227                                        1,
2228                                        NULL,
2229                                        &ctx->misc_parameter_framerate_buf_id[i]);
2230             CHECK_VASTATUS(va_status, "vaCreateBuffer");
2231 
2232             vaMapBuffer(ctx->va_dpy,
2233                         ctx->misc_parameter_framerate_buf_id[i],
2234                         (void **)&misc_param);
2235 
2236             misc_param->type = VAEncMiscParameterTypeFrameRate;
2237             misc_framerate_param = (VAEncMiscParameterFrameRate *)misc_param->data;
2238             misc_framerate_param->framerate = ((100 << 16) | framerate_per_100s);
2239             misc_framerate_param->framerate_flags.bits.temporal_id = i;
2240 
2241             vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_ratecontrol_buf_id[i]);
2242         }
2243 
2244         va_status = vaCreateBuffer(ctx->va_dpy,
2245                                    ctx->context_id,
2246                                    VAEncMiscParameterBufferType,
2247                                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
2248                                    1,
2249                                    NULL,
2250                                    &ctx->misc_parameter_hrd_buf_id);
2251         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2252 
2253         vaMapBuffer(ctx->va_dpy,
2254                     ctx->misc_parameter_hrd_buf_id,
2255                     (void **)&misc_param);
2256 
2257         misc_param->type = VAEncMiscParameterTypeHRD;
2258         misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
2259 
2260         misc_hrd_param->initial_buffer_fullness = ctx->bits_per_kbps * 1024 * 4;
2261         misc_hrd_param->buffer_size = ctx->bits_per_kbps * 1024 * 8;
2262 
2263         vaUnmapBuffer(ctx->va_dpy, ctx->misc_parameter_hrd_buf_id);
2264     }
2265 }
2266 
2267 static void
svcenc_update_packed_slice_header_buffer(struct svcenc_context * ctx,unsigned int temporal_id)2268 svcenc_update_packed_slice_header_buffer(struct svcenc_context *ctx, unsigned int temporal_id)
2269 {
2270     VAStatus va_status;
2271     VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
2272     unsigned int length_in_bits;
2273     unsigned char *packed_header_data_buffer = NULL;
2274     int i;
2275 
2276     for (i = 0; i < ctx->num_slices; i++) {
2277         length_in_bits = build_packed_svc_prefix_nal_unit(&ctx->pic_param,
2278                          temporal_id,
2279                          &packed_header_data_buffer);
2280 
2281         packed_header_param_buffer.type = VAEncPackedHeaderRawData;
2282         packed_header_param_buffer.bit_length = length_in_bits;
2283         packed_header_param_buffer.has_emulation_bytes = 0;
2284 
2285         va_status = vaCreateBuffer(ctx->va_dpy,
2286                                    ctx->context_id,
2287                                    VAEncPackedHeaderParameterBufferType,
2288                                    sizeof(packed_header_param_buffer),
2289                                    1,
2290                                    &packed_header_param_buffer,
2291                                    &ctx->packed_prefix_nal_unit_param_buf_id[i]);
2292         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2293 
2294         va_status = vaCreateBuffer(ctx->va_dpy,
2295                                    ctx->context_id,
2296                                    VAEncPackedHeaderDataBufferType,
2297                                    (length_in_bits + 7) / 8,
2298                                    1,
2299                                    packed_header_data_buffer,
2300                                    &ctx->packed_prefix_nal_unit_data_buf_id[i]);
2301         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2302 
2303         free(packed_header_data_buffer);
2304 
2305         length_in_bits = build_packed_slice_header_buffer(ctx,
2306                          &ctx->seq_param,
2307                          &ctx->pic_param,
2308                          &ctx->slice_param[i],
2309                          ctx->reordering_info,
2310                          &packed_header_data_buffer);
2311 
2312         packed_header_param_buffer.type = VAEncPackedHeaderSlice;
2313         packed_header_param_buffer.bit_length = length_in_bits;
2314         packed_header_param_buffer.has_emulation_bytes = 0;
2315 
2316         va_status = vaCreateBuffer(ctx->va_dpy,
2317                                    ctx->context_id,
2318                                    VAEncPackedHeaderParameterBufferType,
2319                                    sizeof(packed_header_param_buffer),
2320                                    1,
2321                                    &packed_header_param_buffer,
2322                                    &ctx->packed_slice_header_param_buf_id[i]);
2323         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2324 
2325         va_status = vaCreateBuffer(ctx->va_dpy,
2326                                    ctx->context_id,
2327                                    VAEncPackedHeaderDataBufferType,
2328                                    (length_in_bits + 7) / 8,
2329                                    1,
2330                                    packed_header_data_buffer,
2331                                    &ctx->packed_slice_header_data_buf_id[i]);
2332         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2333 
2334         free(packed_header_data_buffer);
2335     }
2336 }
2337 
2338 void
svcenc_update_packed_buffers(struct svcenc_context * ctx,svcenc_surface * current_surface)2339 svcenc_update_packed_buffers(struct svcenc_context *ctx,
2340                              svcenc_surface *current_surface)
2341 {
2342     VAStatus va_status;
2343     VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
2344     unsigned int length_in_bits;
2345     unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL, *packed_sei_buffer = NULL;
2346 
2347     length_in_bits = build_packed_sei_buffer(ctx,
2348                      &ctx->seq_param,
2349                      &ctx->pic_param,
2350                      current_surface,
2351                      &packed_sei_buffer);
2352 
2353     if (packed_sei_buffer) {
2354         assert(length_in_bits);
2355 
2356         packed_header_param_buffer.type = VAEncPackedHeaderRawData;
2357         packed_header_param_buffer.bit_length = length_in_bits;
2358         packed_header_param_buffer.has_emulation_bytes = 0;
2359         va_status = vaCreateBuffer(ctx->va_dpy,
2360                                    ctx->context_id,
2361                                    VAEncPackedHeaderParameterBufferType,
2362                                    sizeof(packed_header_param_buffer),
2363                                    1,
2364                                    &packed_header_param_buffer,
2365                                    &ctx->packed_sei_header_param_buf_id);
2366         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2367 
2368         va_status = vaCreateBuffer(ctx->va_dpy,
2369                                    ctx->context_id,
2370                                    VAEncPackedHeaderDataBufferType,
2371                                    (length_in_bits + 7) / 8,
2372                                    1,
2373                                    packed_sei_buffer,
2374                                    &ctx->packed_sei_buf_id);
2375         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2376 
2377         free(packed_sei_buffer);
2378     }
2379 
2380     if (current_surface->frame_num == 0) {
2381         int save_profile_idc, save_constraint_set_flag;
2382         unsigned char *packed_svc_seq_buffer = NULL;
2383 
2384         length_in_bits = build_packed_seq_buffer(ctx,
2385                          &ctx->seq_param,
2386                          &packed_seq_buffer);
2387 
2388         packed_header_param_buffer.type = VAEncPackedHeaderH264_SPS;
2389         packed_header_param_buffer.bit_length = length_in_bits;
2390         packed_header_param_buffer.has_emulation_bytes = 0;
2391         va_status = vaCreateBuffer(ctx->va_dpy,
2392                                    ctx->context_id,
2393                                    VAEncPackedHeaderParameterBufferType,
2394                                    sizeof(packed_header_param_buffer),
2395                                    1,
2396                                    &packed_header_param_buffer,
2397                                    &ctx->packed_seq_header_param_buf_id);
2398         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2399 
2400         va_status = vaCreateBuffer(ctx->va_dpy,
2401                                    ctx->context_id,
2402                                    VAEncPackedHeaderDataBufferType,
2403                                    (length_in_bits + 7) / 8,
2404                                    1,
2405                                    packed_seq_buffer,
2406                                    &ctx->packed_seq_buf_id);
2407         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2408 
2409         save_profile_idc = ctx->profile_idc;
2410         save_constraint_set_flag = ctx->constraint_set_flag;
2411         ctx->profile_idc = ctx->svc_profile_idc;
2412         ctx->constraint_set_flag = ctx->svc_constraint_set_flag;
2413 
2414         length_in_bits = build_packed_subset_seq_buffer(ctx,
2415                          &ctx->seq_param,
2416                          &packed_svc_seq_buffer);
2417         packed_header_param_buffer.type = VAEncPackedHeaderRawData;
2418         packed_header_param_buffer.bit_length = length_in_bits;
2419         packed_header_param_buffer.has_emulation_bytes = 0;
2420         va_status = vaCreateBuffer(ctx->va_dpy,
2421                                    ctx->context_id,
2422                                    VAEncPackedHeaderParameterBufferType,
2423                                    sizeof(packed_header_param_buffer),
2424                                    1,
2425                                    &packed_header_param_buffer,
2426                                    &ctx->packed_svc_seq_header_param_buf_id);
2427         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2428 
2429         va_status = vaCreateBuffer(ctx->va_dpy,
2430                                    ctx->context_id,
2431                                    VAEncPackedHeaderDataBufferType,
2432                                    (length_in_bits + 7) / 8,
2433                                    1,
2434                                    packed_svc_seq_buffer,
2435                                    &ctx->packed_svc_seq_buf_id);
2436         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2437 
2438         ctx->profile_idc = save_profile_idc;
2439         ctx->constraint_set_flag = save_constraint_set_flag;
2440 
2441         free(packed_svc_seq_buffer);
2442 
2443         length_in_bits = build_packed_pic_buffer(ctx,
2444                          &ctx->pic_param,
2445                          &packed_pic_buffer);
2446         packed_header_param_buffer.type = VAEncPackedHeaderH264_PPS;
2447         packed_header_param_buffer.bit_length = length_in_bits;
2448         packed_header_param_buffer.has_emulation_bytes = 0;
2449 
2450         va_status = vaCreateBuffer(ctx->va_dpy,
2451                                    ctx->context_id,
2452                                    VAEncPackedHeaderParameterBufferType,
2453                                    sizeof(packed_header_param_buffer),
2454                                    1,
2455                                    &packed_header_param_buffer,
2456                                    &ctx->packed_pic_header_param_buf_id);
2457         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2458 
2459         va_status = vaCreateBuffer(ctx->va_dpy,
2460                                    ctx->context_id,
2461                                    VAEncPackedHeaderDataBufferType,
2462                                    (length_in_bits + 7) / 8,
2463                                    1,
2464                                    packed_pic_buffer,
2465                                    &ctx->packed_pic_buf_id);
2466         CHECK_VASTATUS(va_status, "vaCreateBuffer");
2467 
2468         free(packed_seq_buffer);
2469         free(packed_pic_buffer);
2470     }
2471 
2472     svcenc_update_packed_slice_header_buffer(ctx, current_surface->temporal_id);
2473 }
2474 
2475 void
svcenc_update_profile_idc(struct svcenc_context * ctx,svcenc_surface * current_surface)2476 svcenc_update_profile_idc(struct svcenc_context *ctx,
2477                           svcenc_surface *current_surface)
2478 {
2479     ctx->profile_idc = PROFILE_IDC_HIGH;
2480     ctx->constraint_set_flag = 0;
2481 
2482     switch (ctx->profile) {
2483     case VAProfileH264High:
2484         ctx->profile_idc = PROFILE_IDC_HIGH;
2485         ctx->constraint_set_flag |= (1 << 1);
2486         break;
2487 
2488     case VAProfileH264ConstrainedBaseline:
2489         ctx->profile_idc = PROFILE_IDC_BASELINE;
2490         ctx->constraint_set_flag |= (1 << 0 |
2491                                      1 << 1 |
2492                                      1 << 2);
2493         break;
2494 
2495     default:
2496         /* Never get here !!! */
2497         assert(0);
2498         break;
2499     }
2500 
2501     ctx->svc_profile_idc = PROFILE_IDC_SCALABLE_HIGH;
2502     ctx->svc_constraint_set_flag = 0;
2503 
2504     switch (ctx->profile) {
2505     case VAProfileH264High:
2506         ctx->svc_profile_idc = PROFILE_IDC_SCALABLE_HIGH;
2507         ctx->svc_constraint_set_flag |= (1 << 1);
2508         break;
2509 
2510     case VAProfileH264ConstrainedBaseline:
2511         ctx->svc_profile_idc = PROFILE_IDC_SCALABLE_BASELINE;
2512         ctx->svc_constraint_set_flag |= (1 << 0 | 1 << 1 | 1 << 5);
2513         break;
2514 
2515     default:
2516         /* Never get here !!! */
2517         assert(0);
2518         break;
2519     }
2520 }
2521 
2522 int
begin_picture(struct svcenc_context * ctx,svcenc_surface * current_surface)2523 begin_picture(struct svcenc_context *ctx,
2524               svcenc_surface *current_surface)
2525 {
2526     svcenc_update_profile_idc(ctx, current_surface);
2527     svcenc_update_sequence_parameter_buffer(ctx, current_surface);
2528     svcenc_update_picture_parameter_buffer(ctx, current_surface);
2529     svcenc_update_slice_parameter_buffer(ctx, current_surface);
2530     svcenc_update_misc_parameter_buffer(ctx, current_surface);
2531     svcenc_update_packed_buffers(ctx, current_surface);
2532 
2533     return 0;
2534 }
2535 
2536 static int
svcenc_store_coded_buffer(struct svcenc_context * ctx,svcenc_surface * current_surface)2537 svcenc_store_coded_buffer(struct svcenc_context *ctx,
2538                           svcenc_surface *current_surface)
2539 {
2540     VACodedBufferSegment *coded_buffer_segment;
2541     unsigned char *coded_mem;
2542     int slice_data_length;
2543     VAStatus va_status;
2544     size_t w_items;
2545 
2546     va_status = vaSyncSurface(ctx->va_dpy, src_surfaces[current_surface->slot_in_surfaces]);
2547     CHECK_VASTATUS(va_status, "vaSyncSurface");
2548 
2549     va_status = vaMapBuffer(ctx->va_dpy, ctx->codedbuf_buf_id, (void **)(&coded_buffer_segment));
2550     CHECK_VASTATUS(va_status, "vaMapBuffer");
2551 
2552     coded_mem = coded_buffer_segment->buf;
2553 
2554     if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
2555         /* Fatal error !!! */
2556         assert(0);
2557     }
2558 
2559     slice_data_length = coded_buffer_segment->size;
2560 
2561     do {
2562         w_items = fwrite(coded_mem, slice_data_length, 1, ctx->ofp);
2563     } while (w_items != 1);
2564 
2565     vaUnmapBuffer(ctx->va_dpy, ctx->codedbuf_buf_id);
2566 
2567     return 0;
2568 }
2569 
2570 int
render_picture(struct svcenc_context * ctx,svcenc_surface * current_surface)2571 render_picture(struct svcenc_context *ctx,
2572                svcenc_surface *current_surface)
2573 {
2574     VAStatus va_status;
2575     VABufferID va_buffers[32];
2576     unsigned int num_va_buffers = 0;
2577     int i;
2578 
2579     va_buffers[num_va_buffers++] = ctx->seq_param_buf_id;
2580     va_buffers[num_va_buffers++] = ctx->pic_param_buf_id;
2581 
2582     if (ctx->packed_sei_scalability_info_header_param_buf_id != VA_INVALID_ID)
2583         va_buffers[num_va_buffers++] = ctx->packed_sei_scalability_info_header_param_buf_id;
2584 
2585     if (ctx->packed_sei_scalability_info_buf_id != VA_INVALID_ID)
2586         va_buffers[num_va_buffers++] = ctx->packed_sei_scalability_info_buf_id;
2587 
2588     if (ctx->packed_seq_header_param_buf_id != VA_INVALID_ID)
2589         va_buffers[num_va_buffers++] = ctx->packed_seq_header_param_buf_id;
2590 
2591     if (ctx->packed_seq_buf_id != VA_INVALID_ID)
2592         va_buffers[num_va_buffers++] = ctx->packed_seq_buf_id;
2593 
2594     if (ctx->packed_svc_seq_header_param_buf_id != VA_INVALID_ID)
2595         va_buffers[num_va_buffers++] = ctx->packed_svc_seq_header_param_buf_id;
2596 
2597     if (ctx->packed_svc_seq_buf_id != VA_INVALID_ID)
2598         va_buffers[num_va_buffers++] = ctx->packed_svc_seq_buf_id;
2599 
2600     if (ctx->packed_pic_header_param_buf_id != VA_INVALID_ID)
2601         va_buffers[num_va_buffers++] = ctx->packed_pic_header_param_buf_id;
2602 
2603     if (ctx->packed_pic_buf_id != VA_INVALID_ID)
2604         va_buffers[num_va_buffers++] = ctx->packed_pic_buf_id;
2605 
2606     if (ctx->packed_sei_header_param_buf_id != VA_INVALID_ID)
2607         va_buffers[num_va_buffers++] = ctx->packed_sei_header_param_buf_id;
2608 
2609     if (ctx->packed_sei_buf_id != VA_INVALID_ID)
2610         va_buffers[num_va_buffers++] = ctx->packed_sei_buf_id;
2611 
2612     if (ctx->misc_parameter_layer_structure_buf_id != VA_INVALID_ID)
2613         va_buffers[num_va_buffers++] = ctx->misc_parameter_layer_structure_buf_id;
2614 
2615     for (i = 0; i < MAX_LAYERS; i++) {
2616         if (ctx->misc_parameter_ratecontrol_buf_id[i] != VA_INVALID_ID)
2617             va_buffers[num_va_buffers++] = ctx->misc_parameter_ratecontrol_buf_id[i];
2618 
2619         if (ctx->misc_parameter_framerate_buf_id[i] != VA_INVALID_ID)
2620             va_buffers[num_va_buffers++] = ctx->misc_parameter_framerate_buf_id[i];
2621     }
2622 
2623     if (ctx->misc_parameter_hrd_buf_id != VA_INVALID_ID)
2624         va_buffers[num_va_buffers++] =  ctx->misc_parameter_hrd_buf_id;
2625 
2626     va_status = vaBeginPicture(ctx->va_dpy,
2627                                ctx->context_id,
2628                                src_surfaces[current_surface->slot_in_surfaces]);
2629     CHECK_VASTATUS(va_status, "vaBeginPicture");
2630 
2631     va_status = vaRenderPicture(ctx->va_dpy,
2632                                 ctx->context_id,
2633                                 va_buffers,
2634                                 num_va_buffers);
2635     CHECK_VASTATUS(va_status, "vaRenderPicture");
2636 
2637     for (i = 0; i < ctx->num_slices; i++) {
2638         va_status = vaRenderPicture(ctx->va_dpy,
2639                                     ctx->context_id,
2640                                     &ctx->packed_prefix_nal_unit_param_buf_id[i],
2641                                     1);
2642         CHECK_VASTATUS(va_status, "vaRenderPicture");
2643 
2644         va_status = vaRenderPicture(ctx->va_dpy,
2645                                     ctx->context_id,
2646                                     &ctx->packed_prefix_nal_unit_data_buf_id[i],
2647                                     1);
2648         CHECK_VASTATUS(va_status, "vaRenderPicture");
2649 
2650         va_status = vaRenderPicture(ctx->va_dpy,
2651                                     ctx->context_id,
2652                                     &ctx->packed_slice_header_param_buf_id[i],
2653                                     1);
2654         CHECK_VASTATUS(va_status, "vaRenderPicture");
2655 
2656         va_status = vaRenderPicture(ctx->va_dpy,
2657                                     ctx->context_id,
2658                                     &ctx->packed_slice_header_data_buf_id[i],
2659                                     1);
2660         CHECK_VASTATUS(va_status, "vaRenderPicture");
2661 
2662         va_status = vaRenderPicture(ctx->va_dpy,
2663                                     ctx->context_id,
2664                                     &ctx->slice_param_buf_id[i],
2665                                     1);
2666         CHECK_VASTATUS(va_status, "vaRenderPicture");
2667     }
2668 
2669     va_status = vaEndPicture(ctx->va_dpy, ctx->context_id);
2670     CHECK_VASTATUS(va_status, "vaEndPicture");
2671 
2672     svcenc_store_coded_buffer(ctx, current_surface);
2673 
2674     return 0;
2675 }
2676 
2677 static int
svcenc_destroy_buffers(struct svcenc_context * ctx,VABufferID * va_buffers,unsigned int num_va_buffers)2678 svcenc_destroy_buffers(struct svcenc_context *ctx,
2679                        VABufferID *va_buffers,
2680                        unsigned int num_va_buffers)
2681 {
2682     VAStatus va_status;
2683     unsigned int i;
2684 
2685     for (i = 0; i < num_va_buffers; i++) {
2686         if (va_buffers[i] != VA_INVALID_ID) {
2687             va_status = vaDestroyBuffer(ctx->va_dpy, va_buffers[i]);
2688             CHECK_VASTATUS(va_status, "vaDestroyBuffer");
2689             va_buffers[i] = VA_INVALID_ID;
2690         }
2691     }
2692 
2693     return 0;
2694 }
2695 
2696 int
end_picture(struct svcenc_context * ctx,svcenc_surface * current_surface)2697 end_picture(struct svcenc_context *ctx,
2698             svcenc_surface *current_surface)
2699 {
2700     svcenc_destroy_buffers(ctx, &ctx->seq_param_buf_id, 1);
2701     svcenc_destroy_buffers(ctx, &ctx->pic_param_buf_id, 1);
2702     svcenc_destroy_buffers(ctx, &ctx->packed_sei_scalability_info_header_param_buf_id, 1);
2703     svcenc_destroy_buffers(ctx, &ctx->packed_sei_scalability_info_buf_id, 1);
2704     svcenc_destroy_buffers(ctx, &ctx->packed_seq_header_param_buf_id, 1);
2705     svcenc_destroy_buffers(ctx, &ctx->packed_seq_buf_id, 1);
2706     svcenc_destroy_buffers(ctx, &ctx->packed_svc_seq_header_param_buf_id, 1);
2707     svcenc_destroy_buffers(ctx, &ctx->packed_svc_seq_buf_id, 1);
2708     svcenc_destroy_buffers(ctx, &ctx->packed_pic_header_param_buf_id, 1);
2709     svcenc_destroy_buffers(ctx, &ctx->packed_pic_buf_id, 1);
2710     svcenc_destroy_buffers(ctx, &ctx->slice_param_buf_id[0], ctx->num_slices);
2711     svcenc_destroy_buffers(ctx, &ctx->codedbuf_buf_id, 1);
2712     svcenc_destroy_buffers(ctx, &ctx->misc_parameter_layer_structure_buf_id, 1);
2713     svcenc_destroy_buffers(ctx, &ctx->misc_parameter_ratecontrol_buf_id[0], MAX_LAYERS);
2714     svcenc_destroy_buffers(ctx, &ctx->misc_parameter_framerate_buf_id[0], MAX_LAYERS);
2715     svcenc_destroy_buffers(ctx, &ctx->misc_parameter_hrd_buf_id, 1);
2716     svcenc_destroy_buffers(ctx, &ctx->packed_sei_header_param_buf_id, 1);
2717     svcenc_destroy_buffers(ctx, &ctx->packed_sei_buf_id, 1);
2718     svcenc_destroy_buffers(ctx, &ctx->packed_slice_header_param_buf_id[0], ctx->num_slices);
2719     svcenc_destroy_buffers(ctx, &ctx->packed_slice_header_data_buf_id[0], ctx->num_slices);
2720     svcenc_destroy_buffers(ctx, &ctx->packed_prefix_nal_unit_param_buf_id[0], ctx->num_slices);
2721     svcenc_destroy_buffers(ctx, &ctx->packed_prefix_nal_unit_data_buf_id[0], ctx->num_slices);
2722 
2723     memset(ctx->slice_param, 0, sizeof(ctx->slice_param));
2724     ctx->num_slices = 0;
2725 
2726     return 0;
2727 }
2728 
2729 void
encode_picture(struct svcenc_context * ctx,svcenc_surface * current_surface)2730 encode_picture(struct svcenc_context *ctx, svcenc_surface *current_surface)
2731 {
2732     begin_picture(ctx, current_surface);
2733     render_picture(ctx, current_surface);
2734     end_picture(ctx, current_surface);
2735 
2736     svcenc_update_ref_frames(ctx, current_surface);
2737 
2738     if ((current_surface->is_idr) &&
2739         (ctx->rate_control_mode & VA_RC_CBR)) {
2740         ctx->prev_idr_cpb_removal = ctx->current_idr_cpb_removal;
2741     }
2742 }
2743 
2744 static void
svcenc_va_init(struct svcenc_context * ctx)2745 svcenc_va_init(struct svcenc_context *ctx)
2746 {
2747     VAProfile *profile_list;
2748     VAEntrypoint *entrypoint_list;
2749     VAConfigAttrib attrib_list[4];
2750     VAStatus va_status;
2751     int max_profiles, num_profiles = 0, profile = VAProfileNone;
2752     int max_entrypoints, num_entrypoints = 0, entrypoint;
2753     int major_ver, minor_ver;
2754     int i, j;
2755 
2756     ctx->va_dpy = va_open_display();
2757     va_status = vaInitialize(ctx->va_dpy,
2758                              &major_ver,
2759                              &minor_ver);
2760     CHECK_VASTATUS(va_status, "vaInitialize");
2761 
2762     max_profiles = vaMaxNumProfiles(ctx->va_dpy);
2763     profile_list = malloc(max_profiles * sizeof(VAProfile));
2764     assert(profile_list);
2765     vaQueryConfigProfiles(ctx->va_dpy,
2766                           profile_list,
2767                           &num_profiles);
2768 
2769     for (i = 0; i < ARRAY_ELEMS(g_va_profiles); i++) {
2770         for (j = 0; j < num_profiles; j++) {
2771             if (g_va_profiles[i] == profile_list[j]) {
2772                 profile = g_va_profiles[i];
2773                 break;
2774             }
2775         }
2776 
2777         if (profile != VAProfileNone)
2778             break;
2779     }
2780 
2781     free(profile_list);
2782 
2783     if (profile == VAProfileNone) {
2784         fprintf(stderr, "Can't find a supported profile\n");
2785         exit(-1);
2786     }
2787 
2788     ctx->profile = profile;
2789 
2790     max_entrypoints = vaMaxNumEntrypoints(ctx->va_dpy);
2791     entrypoint_list = malloc(max_entrypoints * sizeof(VAEntrypoint));
2792     assert(entrypoint_list);
2793     vaQueryConfigEntrypoints(ctx->va_dpy,
2794                              ctx->profile,
2795                              entrypoint_list,
2796                              &num_entrypoints);
2797 
2798     for (entrypoint = 0; entrypoint < num_entrypoints; entrypoint++) {
2799         if (entrypoint_list[entrypoint] == VAEntrypointEncSlice)
2800             break;
2801     }
2802 
2803     free(entrypoint_list);
2804 
2805     if (entrypoint == num_entrypoints) {
2806         /* not find Slice entry point */
2807         fprintf(stderr, "Can't find the supported entrypoint\n");
2808         exit(-1);
2809     }
2810 
2811     /* find out the format for the render target, and rate control mode */
2812     attrib_list[0].type = VAConfigAttribRTFormat;
2813     attrib_list[1].type = VAConfigAttribRateControl;
2814     attrib_list[2].type = VAConfigAttribEncPackedHeaders;
2815     attrib_list[3].type = VAConfigAttribEncRateControlExt;
2816 
2817     vaGetConfigAttributes(ctx->va_dpy,
2818                           ctx->profile,
2819                           VAEntrypointEncSlice,
2820                           &attrib_list[0],
2821                           4);
2822 
2823     if ((attrib_list[0].value & VA_RT_FORMAT_YUV420) == 0) {
2824         /* not find desired YUV420 RT format */
2825         assert(0);
2826     }
2827 
2828     if ((attrib_list[1].value & ctx->rate_control_mode) == 0) {
2829         /* Can't find matched RC mode */
2830         fprintf(stderr, "RC mode %d isn't found, exit\n", ctx->rate_control_mode);
2831         assert(0);
2832     }
2833 
2834     if ((attrib_list[2].value & (VA_ENC_PACKED_HEADER_SEQUENCE |
2835                                  VA_ENC_PACKED_HEADER_PICTURE |
2836                                  VA_ENC_PACKED_HEADER_SLICE |
2837                                  VA_ENC_PACKED_HEADER_RAW_DATA)) == 0) {
2838         /* Can't find matched PACKED HEADER mode */
2839         assert(0);
2840     }
2841 
2842     if (attrib_list[3].value == VA_ATTRIB_NOT_SUPPORTED) {
2843         ctx->layer_brc = 0; // force to 0
2844     } else {
2845         VAConfigAttribValEncRateControlExt *val = (VAConfigAttribValEncRateControlExt *)&attrib_list[3].value;
2846 
2847         if (!val->bits.max_num_temporal_layers_minus1) {
2848             fprintf(stderr, "Do not support temporal layer\n");
2849             assert(0);
2850         }
2851 
2852         if (ctx->hierarchical_levels > (val->bits.max_num_temporal_layers_minus1 + 1)) {
2853             fprintf(stderr, "Over the maximum number of the supported layers\n");
2854             assert(0);
2855         }
2856 
2857         if (!val->bits.temporal_layer_bitrate_control_flag)
2858             ctx->layer_brc = 0; // force to 0
2859     }
2860 
2861     attrib_list[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
2862     attrib_list[1].value = ctx->rate_control_mode; /* set to desired RC mode */
2863     attrib_list[2].value = (VA_ENC_PACKED_HEADER_SEQUENCE |
2864                             VA_ENC_PACKED_HEADER_PICTURE |
2865                             VA_ENC_PACKED_HEADER_SLICE |
2866                             VA_ENC_PACKED_HEADER_RAW_DATA);
2867 
2868     va_status = vaCreateConfig(ctx->va_dpy,
2869                                ctx->profile,
2870                                VAEntrypointEncSlice,
2871                                attrib_list,
2872                                3,
2873                                &ctx->config_id);
2874     CHECK_VASTATUS(va_status, "vaCreateConfig");
2875 
2876     /* Create a context for this decode pipe */
2877     va_status = vaCreateContext(ctx->va_dpy,
2878                                 ctx->config_id,
2879                                 ctx->width,
2880                                 ctx->height,
2881                                 VA_PROGRESSIVE,
2882                                 0,
2883                                 0,
2884                                 &ctx->context_id);
2885     CHECK_VASTATUS(va_status, "vaCreateContext");
2886 
2887     va_status = vaCreateSurfaces(ctx->va_dpy,
2888                                  VA_RT_FORMAT_YUV420,
2889                                  ctx->width,
2890                                  ctx->height,
2891                                  src_surfaces,
2892                                  NUM_SURFACES,
2893                                  NULL,
2894                                  0);
2895     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
2896 
2897     va_status = vaCreateSurfaces(ctx->va_dpy,
2898                                  VA_RT_FORMAT_YUV420,
2899                                  ctx->width,
2900                                  ctx->height,
2901                                  rec_surfaces,
2902                                  NUM_SURFACES,
2903                                  NULL,
2904                                  0);
2905     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
2906 }
2907 
2908 static void
svcenc_sei_init(struct svcenc_context * ctx)2909 svcenc_sei_init(struct svcenc_context *ctx)
2910 {
2911     if (!(ctx->rate_control_mode & VA_RC_CBR))
2912         return;
2913 
2914     /* it comes for the bps defined in SPS */
2915     ctx->i_initial_cpb_removal_delay = 2 * 90000;
2916     ctx->i_initial_cpb_removal_delay_offset = 2 * 90000;
2917 
2918     ctx->i_cpb_removal_delay = 2;
2919     ctx->i_initial_cpb_removal_delay_length = 24;
2920     ctx->i_cpb_removal_delay_length = 24;
2921     ctx->i_dpb_output_delay_length = 24;
2922     ctx->time_offset_length = 24;
2923 
2924     ctx->prev_idr_cpb_removal = ctx->i_initial_cpb_removal_delay / 90000;
2925     ctx->current_idr_cpb_removal = ctx->prev_idr_cpb_removal;
2926     ctx->current_cpb_removal = 0;
2927     ctx->idr_frame_num = 0;
2928 }
2929 
2930 static void
svcenc_init(struct svcenc_context * ctx)2931 svcenc_init(struct svcenc_context *ctx)
2932 {
2933     int i;
2934 
2935     ctx->frame_data_buffer = (unsigned char *)malloc(ctx->frame_size);
2936     ctx->num_remainder_bframes = 0;
2937     ctx->max_num_ref_frames = ctx->gop_size;
2938     ctx->num_ref_frames = 0;
2939 
2940     switch (ctx->gop_size) {
2941     case 1:
2942         ctx->hierarchical_levels = 1;
2943         break;
2944 
2945     case 2:
2946         ctx->hierarchical_levels = 2;
2947         break;
2948 
2949     case 4:
2950         ctx->hierarchical_levels = 3;
2951         break;
2952 
2953     case 8:
2954         ctx->hierarchical_levels = 4;
2955         break;
2956 
2957     default:
2958         /* Never get here !!! */
2959         assert(0);
2960         break;
2961     }
2962 
2963     if (ctx->gop_type == 1) { // B
2964         ctx->intra_period = 2 * ctx->gop_size;
2965         ctx->ip_period = ctx->gop_size;
2966         ctx->intra_idr_period = 0; // 0 means infinite
2967     } else {
2968         ctx->intra_period = 2 * ctx->gop_size;
2969         ctx->ip_period = 1;
2970         ctx->intra_idr_period = 8 * ctx->intra_period;
2971     }
2972 
2973     ctx->framerate_per_100s = frame_rates[ctx->hierarchical_levels - 1] * 100;
2974 
2975     ctx->upload_task_header = NULL;
2976     ctx->upload_task_tail = NULL;
2977 
2978     ctx->reordering_info[0] = ctx->reordering_info[1] = 0;
2979 
2980     ctx->seq_param_buf_id = VA_INVALID_ID;
2981     ctx->pic_param_buf_id = VA_INVALID_ID;
2982     ctx->packed_sei_scalability_info_header_param_buf_id = VA_INVALID_ID;
2983     ctx->packed_sei_scalability_info_buf_id = VA_INVALID_ID;
2984     ctx->packed_seq_header_param_buf_id = VA_INVALID_ID;
2985     ctx->packed_seq_buf_id = VA_INVALID_ID;
2986     ctx->packed_svc_seq_header_param_buf_id = VA_INVALID_ID;
2987     ctx->packed_svc_seq_buf_id = VA_INVALID_ID;
2988     ctx->packed_pic_header_param_buf_id = VA_INVALID_ID;
2989     ctx->packed_pic_buf_id = VA_INVALID_ID;
2990     ctx->codedbuf_buf_id = VA_INVALID_ID;
2991     ctx->misc_parameter_layer_structure_buf_id = VA_INVALID_ID;
2992 
2993     for (i = 0; i < MAX_LAYERS; i++) {
2994         ctx->misc_parameter_ratecontrol_buf_id[i] = VA_INVALID_ID;
2995         ctx->misc_parameter_framerate_buf_id[i] = VA_INVALID_ID;
2996     }
2997 
2998     ctx->misc_parameter_hrd_buf_id = VA_INVALID_ID;
2999     ctx->packed_sei_header_param_buf_id = VA_INVALID_ID;
3000     ctx->packed_sei_buf_id = VA_INVALID_ID;
3001 
3002     for (i = 0; i < MAX_SLICES; i++) {
3003         ctx->packed_slice_header_param_buf_id[i] = VA_INVALID_ID;
3004         ctx->packed_slice_header_data_buf_id[i] = VA_INVALID_ID;
3005         ctx->packed_prefix_nal_unit_param_buf_id[i] = VA_INVALID_ID;
3006         ctx->packed_prefix_nal_unit_data_buf_id[i] = VA_INVALID_ID;
3007     }
3008 
3009     svcenc_va_init(ctx);
3010 
3011     /* update the next surface status */
3012     ctx->next_svcenc_surface.slot_in_surfaces = 0;
3013     ctx->next_svcenc_surface.coding_order = 0;
3014     ctx->next_svcenc_surface.display_order = 0;
3015     ctx->next_svcenc_surface.temporal_id = 0;
3016     ctx->next_svcenc_surface.frame_num = 0;
3017     ctx->next_svcenc_surface.poc = 0;
3018     ctx->next_svcenc_surface.picture_type = VAEncPictureTypeIntra;
3019     ctx->next_svcenc_surface.is_intra = 1;
3020     ctx->next_svcenc_surface.is_idr = 1;
3021     ctx->next_svcenc_surface.is_ref = 1;
3022     ctx->next_svcenc_surface.rec_surface = rec_surfaces[ctx->next_svcenc_surface.slot_in_surfaces];
3023     memset(src_surface_status, SRC_SURFACE_IN_STORAGE, sizeof(src_surface_status));
3024 
3025     svcenc_sei_init(ctx);
3026 }
3027 
3028 static void
svcenc_run(struct svcenc_context * ctx)3029 svcenc_run(struct svcenc_context *ctx)
3030 {
3031     int coding_order = 0;
3032     svcenc_surface current_surface;
3033 
3034     pthread_create(&ctx->upload_thread, NULL, upload_task_thread, ctx);
3035     current_surface = ctx->next_svcenc_surface;
3036     upload_task_queue(ctx, current_surface.display_order, current_surface.slot_in_surfaces);
3037 
3038     while (coding_order < ctx->num_pictures) {
3039         if (coding_order < (ctx->num_pictures - 1)) {
3040             if (ctx->gop_type == 1) {
3041                 update_next_picture_info(ctx);
3042             } else {
3043                 update_next_picture_info_pgop(ctx);
3044             }
3045 
3046             assert(current_surface.display_order != ctx->next_svcenc_surface.display_order);
3047             upload_task_queue(ctx, ctx->next_svcenc_surface.display_order, ctx->next_svcenc_surface.slot_in_surfaces);
3048         }
3049 
3050         while (src_surface_status[current_surface.slot_in_surfaces] != SRC_SURFACE_IN_ENCODING)
3051             usleep(1);
3052 
3053         encode_picture(ctx, &current_surface);
3054 
3055         if (coding_order < (ctx->num_pictures - 1))
3056             current_surface = ctx->next_svcenc_surface;
3057 
3058         coding_order++;
3059         fprintf(stderr, "\r %d/%d ...", coding_order, ctx->num_pictures);
3060         fflush(stdout);
3061     }
3062 
3063     pthread_join(ctx->upload_thread, NULL);
3064 }
3065 
3066 static void
svcenc_va_end(struct svcenc_context * ctx)3067 svcenc_va_end(struct svcenc_context *ctx)
3068 {
3069     vaDestroySurfaces(ctx->va_dpy, src_surfaces, NUM_SURFACES);
3070     vaDestroySurfaces(ctx->va_dpy, rec_surfaces, NUM_SURFACES);
3071 
3072     vaDestroyContext(ctx->va_dpy, ctx->context_id);
3073     vaDestroyConfig(ctx->va_dpy, ctx->config_id);
3074     vaTerminate(ctx->va_dpy);
3075     va_close_display(ctx->va_dpy);
3076 }
3077 
3078 static void
svcenc_end(struct svcenc_context * ctx)3079 svcenc_end(struct svcenc_context *ctx)
3080 {
3081     free(ctx->frame_data_buffer);
3082     ctx->frame_data_buffer = NULL;
3083     svcenc_va_end(ctx);
3084 }
3085 
3086 int
main(int argc,char * argv[])3087 main(int argc, char *argv[])
3088 {
3089     struct svcenc_context ctx;
3090     struct timeval tpstart, tpend;
3091     float timeuse;
3092 
3093     gettimeofday(&tpstart, NULL);
3094 
3095     memset(&ctx, 0, sizeof(ctx));
3096     parse_args(&ctx, argc, argv);
3097 
3098     svcenc_init(&ctx);
3099     svcenc_run(&ctx);
3100     svcenc_end(&ctx);
3101 
3102     gettimeofday(&tpend, NULL);
3103     timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec;
3104     timeuse /= 1000000;
3105     fprintf(stderr, "\ndone!\n");
3106     fprintf(stderr, "encode %d frames in %f secondes, FPS is %.1f\n", ctx.num_pictures, timeuse, ctx.num_pictures / timeuse);
3107 
3108     svcenc_exit(&ctx, 0);
3109 
3110     return 0;
3111 }
3112