Use existing H.264 SPS as a template rather than building it from scratch
This commit is contained in:
+36
-96
@@ -87,92 +87,61 @@ namespace cbs {
|
|||||||
return write(cbs_ctx, nal, uh, codec_id);
|
return write(cbs_ctx, nal, uh, codec_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::buffer_t<std::uint8_t>
|
h264_t
|
||||||
make_sps_h264(const AVCodecContext *ctx) {
|
make_sps_h264(const AVCodecContext *avctx, const AVPacket *packet) {
|
||||||
H264RawSPS sps {};
|
cbs::ctx_t ctx;
|
||||||
|
if (ff_cbs_init(&ctx, AV_CODEC_ID_H264, nullptr)) {
|
||||||
// b_per_p == ctx->max_b_frames for h264
|
return {};
|
||||||
// desired_b_depth == avoption("b_depth") == 1
|
|
||||||
// max_b_depth == std::min(av_log2(ctx->b_per_p) + 1, desired_b_depth) ==> 1
|
|
||||||
auto max_b_depth = 1;
|
|
||||||
auto dpb_frame = ctx->gop_size == 1 ? 0 : 1 + max_b_depth;
|
|
||||||
auto mb_width = (FFALIGN(ctx->width, 16) / 16) * 16;
|
|
||||||
auto mb_height = (FFALIGN(ctx->height, 16) / 16) * 16;
|
|
||||||
|
|
||||||
sps.nal_unit_header.nal_ref_idc = 3;
|
|
||||||
sps.nal_unit_header.nal_unit_type = H264_NAL_SPS;
|
|
||||||
|
|
||||||
sps.profile_idc = FF_PROFILE_H264_HIGH & 0xFF;
|
|
||||||
|
|
||||||
sps.constraint_set1_flag = 1;
|
|
||||||
|
|
||||||
if (ctx->level != FF_LEVEL_UNKNOWN) {
|
|
||||||
sps.level_idc = ctx->level;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
auto framerate = ctx->framerate;
|
|
||||||
|
|
||||||
auto level = ff_h264_guess_level(
|
cbs::frag_t frag;
|
||||||
sps.profile_idc,
|
|
||||||
ctx->bit_rate,
|
|
||||||
framerate.num / framerate.den,
|
|
||||||
mb_width,
|
|
||||||
mb_height,
|
|
||||||
dpb_frame);
|
|
||||||
|
|
||||||
if (!level) {
|
int err = ff_cbs_read_packet(ctx.get(), &frag, &*packet);
|
||||||
BOOST_LOG(error) << "Could not guess h264 level"sv;
|
if (err < 0) {
|
||||||
|
char err_str[AV_ERROR_MAX_STRING_SIZE] { 0 };
|
||||||
|
BOOST_LOG(error) << "Couldn't read packet: "sv << av_make_error_string(err_str, AV_ERROR_MAX_STRING_SIZE, err);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
sps.level_idc = level->level_idc;
|
|
||||||
|
auto sps_p = ((CodedBitstreamH264Context *) ctx->priv_data)->active_sps;
|
||||||
|
|
||||||
|
// This is a very large struct that cannot safely be stored on the stack
|
||||||
|
auto sps = std::make_unique<H264RawSPS>(*sps_p);
|
||||||
|
|
||||||
|
if (avctx->refs > 0) {
|
||||||
|
sps->max_num_ref_frames = avctx->refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
sps.seq_parameter_set_id = 0;
|
sps->vui_parameters_present_flag = 1;
|
||||||
sps.chroma_format_idc = 1;
|
|
||||||
|
|
||||||
sps.log2_max_frame_num_minus4 = 3; // 4;
|
auto &vui = sps->vui;
|
||||||
sps.pic_order_cnt_type = 0;
|
std::memset(&vui, 0, sizeof(vui));
|
||||||
sps.log2_max_pic_order_cnt_lsb_minus4 = 0; // 4;
|
|
||||||
|
|
||||||
sps.max_num_ref_frames = dpb_frame;
|
|
||||||
|
|
||||||
sps.pic_width_in_mbs_minus1 = mb_width / 16 - 1;
|
|
||||||
sps.pic_height_in_map_units_minus1 = mb_height / 16 - 1;
|
|
||||||
|
|
||||||
sps.frame_mbs_only_flag = 1;
|
|
||||||
sps.direct_8x8_inference_flag = 1;
|
|
||||||
|
|
||||||
if (ctx->width != mb_width || ctx->height != mb_height) {
|
|
||||||
sps.frame_cropping_flag = 1;
|
|
||||||
sps.frame_crop_left_offset = 0;
|
|
||||||
sps.frame_crop_top_offset = 0;
|
|
||||||
sps.frame_crop_right_offset = (mb_width - ctx->width) / 2;
|
|
||||||
sps.frame_crop_bottom_offset = (mb_height - ctx->height) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
sps.vui_parameters_present_flag = 1;
|
|
||||||
|
|
||||||
auto &vui = sps.vui;
|
|
||||||
|
|
||||||
vui.video_format = 5;
|
vui.video_format = 5;
|
||||||
vui.colour_description_present_flag = 1;
|
vui.colour_description_present_flag = 1;
|
||||||
vui.video_signal_type_present_flag = 1;
|
vui.video_signal_type_present_flag = 1;
|
||||||
vui.video_full_range_flag = ctx->color_range == AVCOL_RANGE_JPEG;
|
vui.video_full_range_flag = avctx->color_range == AVCOL_RANGE_JPEG;
|
||||||
vui.colour_primaries = ctx->color_primaries;
|
vui.colour_primaries = avctx->color_primaries;
|
||||||
vui.transfer_characteristics = ctx->color_trc;
|
vui.transfer_characteristics = avctx->color_trc;
|
||||||
vui.matrix_coefficients = ctx->colorspace;
|
vui.matrix_coefficients = avctx->colorspace;
|
||||||
|
|
||||||
vui.low_delay_hrd_flag = 1 - vui.fixed_frame_rate_flag;
|
vui.low_delay_hrd_flag = 1 - vui.fixed_frame_rate_flag;
|
||||||
|
|
||||||
vui.bitstream_restriction_flag = 1;
|
vui.bitstream_restriction_flag = 1;
|
||||||
vui.motion_vectors_over_pic_boundaries_flag = 1;
|
vui.motion_vectors_over_pic_boundaries_flag = 1;
|
||||||
vui.log2_max_mv_length_horizontal = 15;
|
vui.log2_max_mv_length_horizontal = 16;
|
||||||
vui.log2_max_mv_length_vertical = 15;
|
vui.log2_max_mv_length_vertical = 16;
|
||||||
vui.max_num_reorder_frames = max_b_depth;
|
vui.max_num_reorder_frames = 0;
|
||||||
vui.max_dec_frame_buffering = max_b_depth + 1;
|
vui.max_dec_frame_buffering = sps->max_num_ref_frames;
|
||||||
|
|
||||||
return write(sps.nal_unit_header.nal_unit_type, (void *) &sps.nal_unit_header, AV_CODEC_ID_H264);
|
cbs::ctx_t write_ctx;
|
||||||
|
ff_cbs_init(&write_ctx, AV_CODEC_ID_H264, nullptr);
|
||||||
|
|
||||||
|
return h264_t {
|
||||||
|
write(write_ctx, sps->nal_unit_header.nal_unit_type, (void *) &sps->nal_unit_header, AV_CODEC_ID_H264),
|
||||||
|
write(ctx, sps_p->nal_unit_header.nal_unit_type, (void *) &sps_p->nal_unit_header, AV_CODEC_ID_H264)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
hevc_t
|
hevc_t
|
||||||
@@ -248,35 +217,6 @@ namespace cbs {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
util::buffer_t<std::uint8_t>
|
|
||||||
read_sps_h264(const AVPacket *packet) {
|
|
||||||
cbs::ctx_t ctx;
|
|
||||||
if (ff_cbs_init(&ctx, AV_CODEC_ID_H264, nullptr)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
cbs::frag_t frag;
|
|
||||||
|
|
||||||
int err = ff_cbs_read_packet(ctx.get(), &frag, &*packet);
|
|
||||||
if (err < 0) {
|
|
||||||
char err_str[AV_ERROR_MAX_STRING_SIZE] { 0 };
|
|
||||||
BOOST_LOG(error) << "Couldn't read packet: "sv << av_make_error_string(err_str, AV_ERROR_MAX_STRING_SIZE, err);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto h264 = (H264RawNALUnitHeader *) ((CodedBitstreamH264Context *) ctx->priv_data)->active_sps;
|
|
||||||
return write(h264->nal_unit_type, (void *) h264, AV_CODEC_ID_H264);
|
|
||||||
}
|
|
||||||
|
|
||||||
h264_t
|
|
||||||
make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet) {
|
|
||||||
return h264_t {
|
|
||||||
make_sps_h264(ctx),
|
|
||||||
read_sps_h264(packet),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
validate_sps(const AVPacket *packet, int codec_id) {
|
validate_sps(const AVPacket *packet, int codec_id) {
|
||||||
cbs::ctx_t ctx;
|
cbs::ctx_t ctx;
|
||||||
|
|||||||
Reference in New Issue
Block a user