blob: 373d47b45551fa76f5c6571c7e4843729336d50c [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/h264_builder.h"
#include "base/bits.h"
#include "base/notreached.h"
#include "media/filters/h264_bitstream_buffer.h"
namespace media {
void BuildPackedH264SPS(H264BitstreamBuffer& bitstream_buffer,
const H264SPS& sps) {
bitstream_buffer.BeginNALU(H264NALU::kSPS, 3);
bitstream_buffer.AppendBits(8, sps.profile_idc);
bitstream_buffer.AppendBool(sps.constraint_set0_flag);
bitstream_buffer.AppendBool(sps.constraint_set1_flag);
bitstream_buffer.AppendBool(sps.constraint_set2_flag);
bitstream_buffer.AppendBool(sps.constraint_set3_flag);
bitstream_buffer.AppendBool(sps.constraint_set4_flag);
bitstream_buffer.AppendBool(sps.constraint_set5_flag);
bitstream_buffer.AppendBits(2, 0); // reserved_zero_2bits
bitstream_buffer.AppendBits(8, sps.level_idc);
bitstream_buffer.AppendUE(sps.seq_parameter_set_id);
if (sps.profile_idc == H264SPS::kProfileIDCHigh) {
bitstream_buffer.AppendUE(sps.chroma_format_idc);
if (sps.chroma_format_idc == 3) {
bitstream_buffer.AppendBool(sps.separate_colour_plane_flag);
}
bitstream_buffer.AppendUE(sps.bit_depth_luma_minus8);
bitstream_buffer.AppendUE(sps.bit_depth_chroma_minus8);
bitstream_buffer.AppendBool(sps.qpprime_y_zero_transform_bypass_flag);
bitstream_buffer.AppendBool(sps.seq_scaling_matrix_present_flag);
CHECK(!sps.seq_scaling_matrix_present_flag);
}
bitstream_buffer.AppendUE(sps.log2_max_frame_num_minus4);
bitstream_buffer.AppendUE(sps.pic_order_cnt_type);
if (sps.pic_order_cnt_type == 0) {
bitstream_buffer.AppendUE(sps.log2_max_pic_order_cnt_lsb_minus4);
} else if (sps.pic_order_cnt_type == 1) {
// Ignoring the content of this branch as we don't produce
// sps.pic_order_cnt_type == 1
NOTREACHED_NORETURN();
}
bitstream_buffer.AppendUE(sps.max_num_ref_frames);
bitstream_buffer.AppendBool(sps.gaps_in_frame_num_value_allowed_flag);
bitstream_buffer.AppendUE(sps.pic_width_in_mbs_minus1);
bitstream_buffer.AppendUE(sps.pic_height_in_map_units_minus1);
bitstream_buffer.AppendBool(sps.frame_mbs_only_flag);
if (!sps.frame_mbs_only_flag) {
bitstream_buffer.AppendBool(sps.mb_adaptive_frame_field_flag);
}
bitstream_buffer.AppendBool(sps.direct_8x8_inference_flag);
bitstream_buffer.AppendBool(sps.frame_cropping_flag);
if (sps.frame_cropping_flag) {
bitstream_buffer.AppendUE(sps.frame_crop_left_offset);
bitstream_buffer.AppendUE(sps.frame_crop_right_offset);
bitstream_buffer.AppendUE(sps.frame_crop_top_offset);
bitstream_buffer.AppendUE(sps.frame_crop_bottom_offset);
}
bitstream_buffer.AppendBool(sps.vui_parameters_present_flag);
if (sps.vui_parameters_present_flag) {
bitstream_buffer.AppendBool(false); // aspect_ratio_info_present_flag
bitstream_buffer.AppendBool(false); // overscan_info_present_flag
bitstream_buffer.AppendBool(false); // video_signal_type_present_flag
bitstream_buffer.AppendBool(false); // chroma_loc_info_present_flag
bitstream_buffer.AppendBool(sps.timing_info_present_flag);
if (sps.timing_info_present_flag) {
bitstream_buffer.AppendBits(32, sps.num_units_in_tick);
bitstream_buffer.AppendBits(32, sps.time_scale);
bitstream_buffer.AppendBool(sps.fixed_frame_rate_flag);
}
bitstream_buffer.AppendBool(sps.nal_hrd_parameters_present_flag);
if (sps.nal_hrd_parameters_present_flag) {
bitstream_buffer.AppendUE(sps.cpb_cnt_minus1);
bitstream_buffer.AppendBits(4, sps.bit_rate_scale);
bitstream_buffer.AppendBits(4, sps.cpb_size_scale);
CHECK_LT(base::checked_cast<size_t>(sps.cpb_cnt_minus1),
std::size(sps.bit_rate_value_minus1));
for (int i = 0; i <= sps.cpb_cnt_minus1; ++i) {
bitstream_buffer.AppendUE(sps.bit_rate_value_minus1[i]);
bitstream_buffer.AppendUE(sps.cpb_size_value_minus1[i]);
bitstream_buffer.AppendBool(sps.cbr_flag[i]);
}
bitstream_buffer.AppendBits(5,
sps.initial_cpb_removal_delay_length_minus_1);
bitstream_buffer.AppendBits(5, sps.cpb_removal_delay_length_minus1);
bitstream_buffer.AppendBits(5, sps.dpb_output_delay_length_minus1);
bitstream_buffer.AppendBits(5, sps.time_offset_length);
}
bitstream_buffer.AppendBool(false); // vcl_hrd_parameters_flag
if (sps.nal_hrd_parameters_present_flag) {
bitstream_buffer.AppendBool(sps.low_delay_hrd_flag);
}
bitstream_buffer.AppendBool(false); // pic_struct_present_flag
bitstream_buffer.AppendBool(true); // bitstream_restriction_flag
bitstream_buffer.AppendBool(
false); // motion_vectors_over_pic_boundaries_flag
bitstream_buffer.AppendUE(2); // max_bytes_per_pic_denom
bitstream_buffer.AppendUE(1); // max_bits_per_mb_denom
bitstream_buffer.AppendUE(16); // log2_max_mv_length_horizontal
bitstream_buffer.AppendUE(16); // log2_max_mv_length_vertical
// Explicitly set max_num_reorder_frames to 0 to allow the decoder to
// output pictures early.
bitstream_buffer.AppendUE(0); // max_num_reorder_frames
// The value of max_dec_frame_buffering shall be greater than or equal to
// max_num_ref_frames.
const unsigned int max_dec_frame_buffering = sps.max_num_ref_frames;
bitstream_buffer.AppendUE(max_dec_frame_buffering);
}
bitstream_buffer.FinishNALU();
}
void BuildPackedH264PPS(H264BitstreamBuffer& bitstream_buffer,
const H264SPS& sps,
const H264PPS& pps) {
bitstream_buffer.BeginNALU(H264NALU::kPPS, 3);
bitstream_buffer.AppendUE(pps.pic_parameter_set_id);
bitstream_buffer.AppendUE(pps.seq_parameter_set_id);
bitstream_buffer.AppendBool(pps.entropy_coding_mode_flag);
bitstream_buffer.AppendBool(pps.bottom_field_pic_order_in_frame_present_flag);
CHECK_EQ(pps.num_slice_groups_minus1, 0);
bitstream_buffer.AppendUE(pps.num_slice_groups_minus1);
bitstream_buffer.AppendUE(pps.num_ref_idx_l0_default_active_minus1);
bitstream_buffer.AppendUE(pps.num_ref_idx_l1_default_active_minus1);
bitstream_buffer.AppendBool(pps.weighted_pred_flag);
bitstream_buffer.AppendBits(2, pps.weighted_bipred_idc);
bitstream_buffer.AppendSE(pps.pic_init_qp_minus26);
bitstream_buffer.AppendSE(pps.pic_init_qs_minus26);
bitstream_buffer.AppendSE(pps.chroma_qp_index_offset);
bitstream_buffer.AppendBool(pps.deblocking_filter_control_present_flag);
bitstream_buffer.AppendBool(pps.constrained_intra_pred_flag);
bitstream_buffer.AppendBool(pps.redundant_pic_cnt_present_flag);
if (sps.profile_idc >= H264SPS::kProfileIDCHigh) {
bitstream_buffer.AppendBool(pps.transform_8x8_mode_flag);
bitstream_buffer.AppendBool(pps.pic_scaling_matrix_present_flag);
// Ignoring the scaling matrix branch as we don't produce it.
CHECK(!pps.pic_scaling_matrix_present_flag);
bitstream_buffer.AppendSE(pps.second_chroma_qp_index_offset);
}
bitstream_buffer.FinishNALU();
}
} // namespace media