+static void vaapi_encode_h264_write_buffering_period(PutBitContext *pbc,
+ VAAPIEncodeContext *ctx,
+ VAAPIEncodePicture *pic)
+{
+ VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+ VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
+ int i;
+
+ ue(vpic_var(seq_parameter_set_id));
+
+ if (mseq->nal_hrd_parameters_present_flag) {
+ for (i = 0; i <= mseq->cpb_cnt_minus1; i++) {
+ u(mseq->initial_cpb_removal_delay_length_minus1 + 1,
+ mseq_var(initial_cpb_removal_delay));
+ u(mseq->initial_cpb_removal_delay_length_minus1 + 1,
+ mseq_var(initial_cpb_removal_delay_offset));
+ }
+ }
+ if (mseq->vcl_hrd_parameters_present_flag) {
+ av_assert0(0 && "vcl hrd parameters not supported");
+ }
+}
+
+static void vaapi_encode_h264_write_pic_timing(PutBitContext *pbc,
+ VAAPIEncodeContext *ctx,
+ VAAPIEncodePicture *pic)
+{
+ VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
+ VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+ int i, num_clock_ts;
+
+ if (mseq->nal_hrd_parameters_present_flag ||
+ mseq->vcl_hrd_parameters_present_flag) {
+ u(mseq->cpb_removal_delay_length_minus1 + 1,
+ 2 * vseq->num_units_in_tick * priv->cpb_delay,
+ cpb_removal_delay);
+ u(mseq->dpb_output_delay_length_minus1 + 1,
+ 2 * vseq->num_units_in_tick * priv->dpb_delay,
+ dpb_output_delay);
+ }
+ if (mseq->pic_struct_present_flag) {
+ u(4, mseq_var(pic_struct));
+ num_clock_ts = (mseq->pic_struct <= 2 ? 1 :
+ mseq->pic_struct <= 4 ? 2 :
+ mseq->pic_struct <= 8 ? 3 : 0);
+ for (i = 0; i < num_clock_ts; i++) {
+ u(1, 0, clock_timestamp_flag[i]);
+ // No full timestamp information.
+ }
+ }
+}
+
+static void vaapi_encode_h264_write_identifier(PutBitContext *pbc,
+ VAAPIEncodeContext *ctx,
+ VAAPIEncodePicture *pic)
+{
+ const char *lavc = LIBAVCODEC_IDENT;
+ const char *vaapi = VA_VERSION_S;
+ const char *driver = vaQueryVendorString(ctx->hwctx->display);
+ char tmp[256];
+ int i;
+
+ // Random (version 4) ISO 11578 UUID.
+ uint8_t uuid[16] = {
+ 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf,
+ 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d,
+ };
+
+ for (i = 0; i < 16; i++)
+ u(8, uuid[i], uuid_iso_iec_11578);
+
+ snprintf(tmp, sizeof(tmp), "%s / VAAPI %s / %s", lavc, vaapi, driver);
+ for (i = 0; i < sizeof(tmp) && tmp[i]; i++)
+ u(8, tmp[i], user_data_payload_byte);
+}
+
+static void vaapi_encode_h264_write_sei(PutBitContext *pbc,
+ VAAPIEncodeContext *ctx,
+ VAAPIEncodePicture *pic)
+{
+ VAAPIEncodeH264Context *priv = ctx->priv_data;
+ PutBitContext payload_bits;
+ char payload[256];
+ int payload_type, payload_size, i;
+ void (*write_payload)(PutBitContext *pbc,
+ VAAPIEncodeContext *ctx,
+ VAAPIEncodePicture *pic) = NULL;
+
+ vaapi_encode_h264_write_nal_header(pbc, NAL_SEI, 0);
+
+ for (payload_type = 0; payload_type < 64; payload_type++) {
+ switch (payload_type) {
+ case SEI_TYPE_BUFFERING_PERIOD:
+ if (!priv->send_timing_sei ||
+ pic->type != PICTURE_TYPE_IDR)
+ continue;
+ write_payload = &vaapi_encode_h264_write_buffering_period;
+ break;
+ case SEI_TYPE_PIC_TIMING:
+ if (!priv->send_timing_sei)
+ continue;
+ write_payload = &vaapi_encode_h264_write_pic_timing;
+ break;
+ case SEI_TYPE_USER_DATA_UNREGISTERED:
+ if (pic->encode_order != 0)
+ continue;
+ write_payload = &vaapi_encode_h264_write_identifier;
+ break;
+ default:
+ continue;
+ }
+
+ init_put_bits(&payload_bits, payload, sizeof(payload));
+ write_payload(&payload_bits, ctx, pic);
+ if (put_bits_count(&payload_bits) & 7) {
+ write_u(&payload_bits, 1, 1, bit_equal_to_one);
+ while (put_bits_count(&payload_bits) & 7)
+ write_u(&payload_bits, 1, 0, bit_equal_to_zero);
+ }
+ payload_size = put_bits_count(&payload_bits) / 8;
+ flush_put_bits(&payload_bits);
+
+ u(8, payload_type, last_payload_type_byte);
+ u(8, payload_size, last_payload_size_byte);
+ for (i = 0; i < payload_size; i++)
+ u(8, payload[i] & 0xff, sei_payload);
+ }
+
+ vaapi_encode_h264_write_trailing_rbsp(pbc);
+}
+