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, ¤t_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