From 1dd144b49f331ff35de9c7a399e87e723920fe55 Mon Sep 17 00:00:00 2001 From: jan falkin Date: Thu, 5 Aug 2021 14:43:10 -0700 Subject: [PATCH 01/11] patch applied cleanly to release 4.4 using n4.5-dev patch --- configure | 13 + libavcodec/h2645_parse.h | 1 + libavcodec/h264_parse.h | 1 + libavcodec/h264_parser.c | 547 +++++++++++++++++++++++++-------------- libavcodec/internal.h | 5 + libavcodec/libx265.c | 33 +++ libavcodec/nvenc.c | 2 +- libavformat/avformat.h | 10 + libavformat/dashenc.c | 348 ++++++++++++++++++++++++- libavformat/isom.h | 6 + libavformat/movenc.c | 73 ++++-- libavformat/movenc.h | 7 +- libavformat/movenccenc.c | 411 ++++++++++++++++++++++------- libavformat/movenccenc.h | 49 +++- libavformat/segment.c | 56 +++- libavutil/aes.c | 30 ++- libavutil/aes.h | 5 + libavutil/aes_internal.h | 2 + 18 files changed, 1258 insertions(+), 341 deletions(-) diff --git a/configure b/configure index 4ba72bf84b6fc..8b13e8274ef89 100755 --- a/configure +++ b/configure @@ -4756,6 +4756,10 @@ probe_cc(){ _flags_filter=cparser_flags fi + # Debug: + #_cflags_speed='-O0' + #_cflags_size='-O0' + eval ${pfx}_type=\$_type eval ${pfx}_ident=\$_ident } @@ -4784,6 +4788,14 @@ cc_ldflags=$_ldflags set_ccvars CC set_ccvars CXX +echo "cflags_filter: $cflags_filter" +echo "cflags_speed: $cflags_speed" +echo "cflags_size: $cflags_size" +echo "cflags_noopt: $cflags_noopt" +echo "_flags: $_flags" +echo "cc_ldflags: $_ldflags" + + probe_cc hostcc "$host_cc" host_cflags_filter=$_flags_filter host_cflags_speed=$_cflags_speed @@ -6919,6 +6931,7 @@ if [ -z "$optflags" ]; then optflags=$cflags_noopt fi fi +echo "optflags: $optflags" check_optflags(){ check_cflags "$@" diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 3e47f86c53b2f..b29ab354723e7 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -68,6 +68,7 @@ typedef struct H2645NAL { * H.264 only, nal_ref_idc */ int ref_idc; + int slice_header_len_bits; } H2645NAL; typedef struct H2645RBSP { diff --git a/libavcodec/h264_parse.h b/libavcodec/h264_parse.h index 4d016201256ca..b53d0c99128da 100644 --- a/libavcodec/h264_parse.h +++ b/libavcodec/h264_parse.h @@ -90,4 +90,5 @@ int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps, */ int ff_h264_get_profile(const SPS *sps); + #endif /* AVCODEC_H264_PARSE_H */ diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index aacd44cf3b5cc..d8eb73596ee22 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -56,14 +56,22 @@ typedef struct H264ParseContext { int is_avc; int nal_length_size; int got_first; - int picture_structure; + enum AVPictureStructure picture_structure, last_picture_structure; uint8_t parse_history[6]; int parse_history_count; int parse_last_mb; int64_t reference_dts; - int last_frame_num, last_picture_structure; + int last_frame_num; + int curr_pic_num, max_pic_num; + MMCO mmco[MAX_MMCO_COUNT]; + H2645NAL nals[MAX_SLICES]; // assume MAX_SLICES is the most NALs in a packet } H264ParseContext; +void* avpriv_h264_extract_nals(AVCodecParserContext *s) +{ + H264ParseContext *p = s->priv_data; + return p->nals; +} static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, int buf_size, void *logctx) @@ -155,81 +163,321 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, return i - (state & 5); } -static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb, - void *logctx) +/** + * Copy of: + * int ff_h264_decode_ref_pic_marking(H264SliceContext *sl, GetBitContext *gb, + * const H2645NAL *nal, void *logctx) + */ +static int decode_ref_pic_marking(H264ParseContext *p, GetBitContext *gb, + const H2645NAL *nal, void *logctx) { - H264PredWeightTable pwt; - int slice_type_nos = s->pict_type & 3; + int i; + MMCO *mmco = p->mmco; + int nb_mmco = 0; + int explicit_ref_marking; + + if (nal->type == H264_NAL_IDR_SLICE) { // FIXME fields + skip_bits1(gb); // broken_link + if (get_bits1(gb)) { + mmco[0].opcode = MMCO_LONG; + mmco[0].long_arg = 0; + nb_mmco = 1; + } + explicit_ref_marking = 1; + } else { + explicit_ref_marking = get_bits1(gb); + if (explicit_ref_marking) { + for (i = 0; i < MAX_MMCO_COUNT; i++) { + MMCOOpcode opcode = get_ue_golomb_31(gb); + + mmco[i].opcode = opcode; + if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) { + mmco[i].short_pic_num = + (p->curr_pic_num - get_ue_golomb_long(gb) - 1) & + (p->max_pic_num - 1); + } + if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED || + opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) { + unsigned int long_arg = get_ue_golomb_31(gb); + if (long_arg >= 32 || + (long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG && + long_arg == 16) && + !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE(p)))) { + av_log(logctx, AV_LOG_ERROR, + "illegal long ref in memory management control " + "operation %d\n", opcode); + nb_mmco = i; + return -1; + } + mmco[i].long_arg = long_arg; + } + + if (opcode > (unsigned) MMCO_LONG) { + av_log(logctx, AV_LOG_ERROR, + "illegal memory management control operation %d\n", + opcode); + nb_mmco = i; + return -1; + } + if (opcode == MMCO_END) + break; + } + nb_mmco = i; + } + } + + return 0; +} + +/** + * Significant portions copied from h264_slice_header_parse + */ +static int parse_slice(AVCodecParserContext *s, AVCodecContext *avctx, + H2645NAL *nal) +{ + GetBitContext *gb = &nal->gb; H264ParseContext *p = s->priv_data; + const PPS *pps = p->ps.pps; + const SPS *sps = p->ps.sps; + int field_poc[2]; + int ret; + int slice_type_nos = s->pict_type & 3; int list_count, ref_count[2]; + int index, tmp, i; + H264PredWeightTable pwt; + int got_reset = 0; + int deblocking_filter; + /* Decode POC of this picture. + * The prev_ values needed for decoding POC of the next picture are not set here. */ + field_poc[0] = field_poc[1] = INT_MAX; + ret = ff_h264_init_poc(field_poc, &s->output_picture_number, sps, + &p->poc, p->picture_structure, nal->ref_idc); + if (ret < 0) + return ret; - if (p->ps.pps->redundant_pic_cnt_present) - get_ue_golomb(gb); // redundant_pic_count + if (pps->redundant_pic_cnt_present) + get_ue_golomb(gb); /* redundant_pic_cnt */ if (slice_type_nos == AV_PICTURE_TYPE_B) - get_bits1(gb); // direct_spatial_mv_pred + get_bits1(gb); /* direct_spatial_mv_pred_flag */ - if (ff_h264_parse_ref_count(&list_count, ref_count, gb, p->ps.pps, - slice_type_nos, p->picture_structure, logctx) < 0) + /* num_ref_idx_active_override_flag */ + if (ff_h264_parse_ref_count(&list_count, ref_count, gb, pps, + slice_type_nos, p->picture_structure, avctx) < 0) return AVERROR_INVALIDDATA; + /* ref_pic_list_modification */ if (slice_type_nos != AV_PICTURE_TYPE_I) { + /* ff_h264_decode_ref_pic_list_reordering */ int list; for (list = 0; list < list_count; list++) { - if (get_bits1(gb)) { - int index; - for (index = 0; ; index++) { - unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(gb); - - if (reordering_of_pic_nums_idc < 3) - get_ue_golomb_long(gb); - else if (reordering_of_pic_nums_idc > 3) { - av_log(logctx, AV_LOG_ERROR, - "illegal reordering_of_pic_nums_idc %d\n", - reordering_of_pic_nums_idc); - return AVERROR_INVALIDDATA; - } else - break; + if (!get_bits1(gb)) // ref_pic_list_modification_flag_l[01] + continue; - if (index >= ref_count[list]) { - av_log(logctx, AV_LOG_ERROR, - "reference count %d overflow\n", index); - return AVERROR_INVALIDDATA; - } + for (index = 0; ; index++) { + unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(gb); + + if (reordering_of_pic_nums_idc < 3) + get_ue_golomb_long(gb); + else if (reordering_of_pic_nums_idc > 3) { + av_log(avctx, AV_LOG_ERROR, + "illegal reordering_of_pic_nums_idc %d\n", + reordering_of_pic_nums_idc); + return AVERROR_INVALIDDATA; + } else + break; + + if (index >= ref_count[list]) { + av_log(avctx, AV_LOG_ERROR, + "reference count %d overflow\n", index); + return AVERROR_INVALIDDATA; } } } } - if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) || - (p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos == AV_PICTURE_TYPE_B)) - ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos, - &pwt, p->picture_structure, logctx); - - if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag - int i; - for (i = 0; i < MAX_MMCO_COUNT; i++) { - MMCOOpcode opcode = get_ue_golomb_31(gb); - if (opcode > (unsigned) MMCO_LONG) { - av_log(logctx, AV_LOG_ERROR, - "illegal memory management control operation %d\n", - opcode); + /* pred_weight_table */ + if ((pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) || + (pps->weighted_bipred_idc == 1 && slice_type_nos == AV_PICTURE_TYPE_B)) + ff_h264_pred_weight_table(gb, sps, ref_count, slice_type_nos, + &pwt, p->picture_structure, avctx); + + /* dec_ref_pic_marking - sets mmco */ + if (nal->ref_idc) { + ret = decode_ref_pic_marking(p, gb, nal, avctx); + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + } + /* FIXME: MMCO_RESET could appear in non-first slice. + * Maybe, we should parse all undisposable non-IDR slice of this + * picture until encountering MMCO_RESET in a slice of it. */ + for (i = 0; (unsigned int)i < MAX_MMCO_COUNT; i++) { + if (p->mmco[i].opcode == MMCO_END) + break; + if (p->mmco[i].opcode == MMCO_RESET) { + got_reset = 1; + break; + } + } + + /* Set up the prev_ values for decoding POC of the next picture. */ + p->poc.prev_frame_num = got_reset ? 0 : p->poc.frame_num; + p->poc.prev_frame_num_offset = got_reset ? 0 : p->poc.frame_num_offset; + if (nal->ref_idc != 0) { + if (!got_reset) { + p->poc.prev_poc_msb = p->poc.poc_msb; + p->poc.prev_poc_lsb = p->poc.poc_lsb; + } else { + p->poc.prev_poc_msb = 0; + p->poc.prev_poc_lsb = + p->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0]; + } + } + + if (p->sei.picture_timing.present) { + ret = ff_h264_sei_process_picture_timing(&p->sei.picture_timing, + sps, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error processing the picture timing SEI\n"); + p->sei.picture_timing.present = 0; + } + } + + if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { + switch (p->sei.picture_timing.pic_struct) { + case H264_SEI_PIC_STRUCT_TOP_FIELD: + case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: + s->repeat_pict = 0; + break; + case H264_SEI_PIC_STRUCT_FRAME: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP: + s->repeat_pict = 1; + break; + case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + s->repeat_pict = 2; + break; + case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: + s->repeat_pict = 3; + break; + case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: + s->repeat_pict = 5; + break; + default: + s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; + break; + } + } else { + s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; + } + + if (p->picture_structure == PICT_FRAME) { + s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { + switch (p->sei.picture_timing.pic_struct) { + case H264_SEI_PIC_STRUCT_TOP_BOTTOM: + case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + s->field_order = AV_FIELD_TT; + break; + case H264_SEI_PIC_STRUCT_BOTTOM_TOP: + case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + s->field_order = AV_FIELD_BB; + break; + default: + s->field_order = AV_FIELD_PROGRESSIVE; + break; + } + } else { + if (field_poc[0] < field_poc[1]) + s->field_order = AV_FIELD_TT; + else if (field_poc[0] > field_poc[1]) + s->field_order = AV_FIELD_BB; + else + s->field_order = AV_FIELD_PROGRESSIVE; + } + } else { + if (p->picture_structure == PICT_TOP_FIELD) + s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD; + else + s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; + if (p->poc.frame_num == p->last_frame_num && + p->last_picture_structure != AV_PICTURE_STRUCTURE_UNKNOWN && + p->last_picture_structure != AV_PICTURE_STRUCTURE_FRAME && + p->last_picture_structure != s->picture_structure) { + if (p->last_picture_structure == AV_PICTURE_STRUCTURE_TOP_FIELD) + s->field_order = AV_FIELD_TT; + else + s->field_order = AV_FIELD_BB; + } else { + s->field_order = AV_FIELD_UNKNOWN; + } + p->last_picture_structure = s->picture_structure; + p->last_frame_num = p->poc.frame_num; + } + + /* cabac_init_idc */ + if (slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) { + tmp = get_ue_golomb_31(gb); + if (tmp > 2) { + av_log(avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp); + return AVERROR_INVALIDDATA; + } + // sl->cabac_init_idc = tmp; + } + + /* slice_qp_delta */ + // sl->last_qscale_diff = 0; + // tmp = pps->init_qp + (unsigned)get_se_golomb(&sl->gb); + tmp = pps->init_qp + (unsigned)get_se_golomb(gb); + if (tmp > 51 + 6 * (sps->bit_depth_luma - 8)) { + av_log(avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); + return AVERROR_INVALIDDATA; + } + // sl->qscale = tmp; + // sl->chroma_qp[0] = get_chroma_qp(pps, 0, sl->qscale); + // sl->chroma_qp[1] = get_chroma_qp(pps, 1, sl->qscale); + // FIXME qscale / qp ... stuff + if (s->pict_type == AV_PICTURE_TYPE_SP) + get_bits1(gb); /* sp_for_switch_flag */ + if (s->pict_type == AV_PICTURE_TYPE_SP || + s->pict_type == AV_PICTURE_TYPE_SI) + get_se_golomb(gb); /* slice_qs_delta */ + + // sl->deblocking_filter = 1; + // sl->slice_alpha_c0_offset = 0; + // sl->slice_beta_offset = 0; + if (pps->deblocking_filter_parameters_present) { + tmp = get_ue_golomb_31(gb); /* disable_deblocking_filter_idc */ + if (tmp > 2) { + av_log(avctx, AV_LOG_ERROR, + "deblocking_filter_idc %u out of range\n", tmp); + return AVERROR_INVALIDDATA; + } + deblocking_filter = tmp; + if (deblocking_filter < 2) + deblocking_filter ^= 1; // 1<->0 + + if (deblocking_filter) { + int slice_alpha_c0_offset_div2 = get_se_golomb(gb); + int slice_beta_offset_div2 = get_se_golomb(gb); + if (slice_alpha_c0_offset_div2 > 6 || + slice_alpha_c0_offset_div2 < -6 || + slice_beta_offset_div2 > 6 || + slice_beta_offset_div2 < -6) { + av_log(avctx, AV_LOG_ERROR, + "deblocking filter parameters %d %d out of range\n", + slice_alpha_c0_offset_div2, slice_beta_offset_div2); return AVERROR_INVALIDDATA; } - if (opcode == MMCO_END) - return 0; - else if (opcode == MMCO_RESET) - return 1; - - if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) - get_ue_golomb_long(gb); // difference_of_pic_nums_minus1 - if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED || - opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) - get_ue_golomb_31(gb); + // sl->slice_alpha_c0_offset = slice_alpha_c0_offset_div2 * 2; + // sl->slice_beta_offset = slice_beta_offset_div2 * 2; } } + /* slice_group_change_cycle */ + return 0; } @@ -247,14 +495,17 @@ static inline int parse_nal_units(AVCodecParserContext *s, { H264ParseContext *p = s->priv_data; H2645RBSP rbsp = { NULL }; - H2645NAL nal = { NULL }; + H2645NAL *nal; int buf_index, next_avc; unsigned int pps_id; unsigned int slice_type; - int state = -1, got_reset = 0; - int q264 = buf_size >=4 && !memcmp("Q264", buf, 4); - int field_poc[2]; + int state = -1; int ret; + int nal_index = 0; + int q264 = buf_size >=4 && !memcmp("Q264", buf, 4); + int picture_found = 0; + + memset(p->nals, 0, sizeof(p->nals)); /* set some sane default values */ s->pict_type = AV_PICTURE_TYPE_I; @@ -290,8 +541,14 @@ static inline int parse_nal_units(AVCodecParserContext *s, continue; } src_length = next_avc - buf_index; - state = buf[buf_index]; + + if ((unsigned int)nal_index >= sizeof(p->nals)) { + av_log(avctx, AV_LOG_WARNING, "reached NAL parse limit: %lu\n", sizeof(p->nals)); + goto fail; + } + nal = &p->nals[nal_index]; + switch (state & 0x1f) { case H264_NAL_SLICE: case H264_NAL_IDR_SLICE: @@ -308,29 +565,29 @@ static inline int parse_nal_units(AVCodecParserContext *s, } break; } - consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &rbsp, &nal, 1); + consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &rbsp, nal, 1); if (consumed < 0) break; buf_index += consumed; - ret = init_get_bits8(&nal.gb, nal.data, nal.size); + ret = init_get_bits8(&nal->gb, nal->data, nal->size); if (ret < 0) goto fail; - get_bits1(&nal.gb); - nal.ref_idc = get_bits(&nal.gb, 2); - nal.type = get_bits(&nal.gb, 5); + get_bits1(&nal->gb); + nal->ref_idc = get_bits(&nal->gb, 2); + nal->type = get_bits(&nal->gb, 5); - switch (nal.type) { + switch (nal->type) { case H264_NAL_SPS: - ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps, 0); + ff_h264_decode_seq_parameter_set(&nal->gb, avctx, &p->ps, 0); break; case H264_NAL_PPS: - ff_h264_decode_picture_parameter_set(&nal.gb, avctx, &p->ps, - nal.size_bits); + ff_h264_decode_picture_parameter_set(&nal->gb, avctx, &p->ps, + nal->size_bits); break; case H264_NAL_SEI: - ff_h264_sei_decode(&p->sei, &nal.gb, &p->ps, avctx); + ff_h264_sei_decode(&p->sei, &nal->gb, &p->ps, avctx); break; case H264_NAL_IDR_SLICE: s->key_frame = 1; @@ -341,14 +598,15 @@ static inline int parse_nal_units(AVCodecParserContext *s, p->poc.prev_poc_lsb = 0; /* fall through */ case H264_NAL_SLICE: - get_ue_golomb_long(&nal.gb); // skip first_mb_in_slice - slice_type = get_ue_golomb_31(&nal.gb); + picture_found = 1; + get_ue_golomb_long(&nal->gb); // skip first_mb_in_slice + slice_type = get_ue_golomb_31(&nal->gb); s->pict_type = ff_h264_golomb_to_pict_type[slice_type % 5]; if (p->sei.recovery_point.recovery_frame_cnt >= 0) { /* key frame, since recovery_frame_cnt is set */ s->key_frame = 1; } - pps_id = get_ue_golomb(&nal.gb); + pps_id = get_ue_golomb(&nal->gb); if (pps_id >= MAX_PPS_COUNT) { av_log(avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id); @@ -374,7 +632,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (p->ps.sps->ref_frame_count <= 1 && p->ps.pps->ref_count[0] <= 1 && s->pict_type == AV_PICTURE_TYPE_I) s->key_frame = 1; - p->poc.frame_num = get_bits(&nal.gb, sps->log2_max_frame_num); + p->poc.frame_num = get_bits(&nal->gb, sps->log2_max_frame_num); s->coded_width = 16 * sps->mb_width; s->coded_height = 16 * sps->mb_height; @@ -411,151 +669,50 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (sps->frame_mbs_only_flag) { p->picture_structure = PICT_FRAME; } else { - if (get_bits1(&nal.gb)) { // field_pic_flag - p->picture_structure = PICT_TOP_FIELD + get_bits1(&nal.gb); // bottom_field_flag + if (get_bits1(&nal->gb)) { // field_pic_flag + p->picture_structure = PICT_TOP_FIELD + get_bits1(&nal->gb); // bottom_field_flag } else { p->picture_structure = PICT_FRAME; } } - if (nal.type == H264_NAL_IDR_SLICE) - get_ue_golomb_long(&nal.gb); /* idr_pic_id */ + if (p->picture_structure == PICT_FRAME) { + p->curr_pic_num = p->poc.frame_num; + p->max_pic_num = 1 << sps->log2_max_frame_num; + } else { + p->curr_pic_num = 2 * p->poc.frame_num + 1; + p->max_pic_num = 1 << (sps->log2_max_frame_num + 1); + } + if (nal->type == H264_NAL_IDR_SLICE) + get_ue_golomb_long(&nal->gb); /* idr_pic_id */ if (sps->poc_type == 0) { - p->poc.poc_lsb = get_bits(&nal.gb, sps->log2_max_poc_lsb); + p->poc.poc_lsb = get_bits(&nal->gb, sps->log2_max_poc_lsb); if (p->ps.pps->pic_order_present == 1 && p->picture_structure == PICT_FRAME) - p->poc.delta_poc_bottom = get_se_golomb(&nal.gb); + p->poc.delta_poc_bottom = get_se_golomb(&nal->gb); } if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) { - p->poc.delta_poc[0] = get_se_golomb(&nal.gb); + p->poc.delta_poc[0] = get_se_golomb(&nal->gb); if (p->ps.pps->pic_order_present == 1 && p->picture_structure == PICT_FRAME) - p->poc.delta_poc[1] = get_se_golomb(&nal.gb); + p->poc.delta_poc[1] = get_se_golomb(&nal->gb); } - /* Decode POC of this picture. - * The prev_ values needed for decoding POC of the next picture are not set here. */ - field_poc[0] = field_poc[1] = INT_MAX; - ret = ff_h264_init_poc(field_poc, &s->output_picture_number, sps, - &p->poc, p->picture_structure, nal.ref_idc); - if (ret < 0) + // TODO move the other half of the slice-parsing code into this function + ret = parse_slice(s, avctx, nal); + if (ret != 0) { goto fail; - - /* Continue parsing to check if MMCO_RESET is present. - * FIXME: MMCO_RESET could appear in non-first slice. - * Maybe, we should parse all undisposable non-IDR slice of this - * picture until encountering MMCO_RESET in a slice of it. */ - if (nal.ref_idc && nal.type != H264_NAL_IDR_SLICE) { - got_reset = scan_mmco_reset(s, &nal.gb, avctx); - if (got_reset < 0) - goto fail; - } - - /* Set up the prev_ values for decoding POC of the next picture. */ - p->poc.prev_frame_num = got_reset ? 0 : p->poc.frame_num; - p->poc.prev_frame_num_offset = got_reset ? 0 : p->poc.frame_num_offset; - if (nal.ref_idc != 0) { - if (!got_reset) { - p->poc.prev_poc_msb = p->poc.poc_msb; - p->poc.prev_poc_lsb = p->poc.poc_lsb; - } else { - p->poc.prev_poc_msb = 0; - p->poc.prev_poc_lsb = - p->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0]; - } - } - - if (p->sei.picture_timing.present) { - ret = ff_h264_sei_process_picture_timing(&p->sei.picture_timing, - sps, avctx); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error processing the picture timing SEI\n"); - p->sei.picture_timing.present = 0; - } } - - if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { - switch (p->sei.picture_timing.pic_struct) { - case H264_SEI_PIC_STRUCT_TOP_FIELD: - case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: - s->repeat_pict = 0; - break; - case H264_SEI_PIC_STRUCT_FRAME: - case H264_SEI_PIC_STRUCT_TOP_BOTTOM: - case H264_SEI_PIC_STRUCT_BOTTOM_TOP: - s->repeat_pict = 1; - break; - case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: - case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: - s->repeat_pict = 2; - break; - case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: - s->repeat_pict = 3; - break; - case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: - s->repeat_pict = 5; - break; - default: - s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; - break; - } - } else { - s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0; - } - - if (p->picture_structure == PICT_FRAME) { - s->picture_structure = AV_PICTURE_STRUCTURE_FRAME; - if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { - switch (p->sei.picture_timing.pic_struct) { - case H264_SEI_PIC_STRUCT_TOP_BOTTOM: - case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: - s->field_order = AV_FIELD_TT; - break; - case H264_SEI_PIC_STRUCT_BOTTOM_TOP: - case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: - s->field_order = AV_FIELD_BB; - break; - default: - s->field_order = AV_FIELD_PROGRESSIVE; - break; - } - } else { - if (field_poc[0] < field_poc[1]) - s->field_order = AV_FIELD_TT; - else if (field_poc[0] > field_poc[1]) - s->field_order = AV_FIELD_BB; - else - s->field_order = AV_FIELD_PROGRESSIVE; - } - } else { - if (p->picture_structure == PICT_TOP_FIELD) - s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD; - else - s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; - if (p->poc.frame_num == p->last_frame_num && - p->last_picture_structure != AV_PICTURE_STRUCTURE_UNKNOWN && - p->last_picture_structure != AV_PICTURE_STRUCTURE_FRAME && - p->last_picture_structure != s->picture_structure) { - if (p->last_picture_structure == AV_PICTURE_STRUCTURE_TOP_FIELD) - s->field_order = AV_FIELD_TT; - else - s->field_order = AV_FIELD_BB; - } else { - s->field_order = AV_FIELD_UNKNOWN; - } - p->last_picture_structure = s->picture_structure; - p->last_frame_num = p->poc.frame_num; - } - - av_freep(&rbsp.rbsp_buffer); - return 0; /* no need to evaluate the rest */ + nal->slice_header_len_bits = nal->gb.index; + break; } + nal_index++; } - if (q264) { + if (q264 || picture_found) { av_freep(&rbsp.rbsp_buffer); return 0; } diff --git a/libavcodec/internal.h b/libavcodec/internal.h index d889c1883e77b..6ee174b670804 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -378,6 +378,11 @@ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); int ff_alloc_timecode_sei(const AVFrame *frame, AVRational rate, size_t prefix_len, void **data, size_t *sei_size); +/** + * Returns an array of H2645NALs + */ +void* avpriv_h264_extract_nals(AVCodecParserContext *s); + /** * Get an estimated video bitrate based on frame size, frame rate and coded * bits per pixel. diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index b2008e96f1c3d..47328f788b242 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -45,6 +45,9 @@ typedef struct libx265Context { float crf; int cqp; int forced_idr; + char *max_cll; + char *master_display; + int bframes; char *preset; char *tune; char *profile; @@ -303,6 +306,33 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) return ret; } + if (ctx->max_cll != 0) { + if (ctx->api->param_parse(ctx->params, "max-cll", ctx->max_cll) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid max_cll: %s.\n", ctx->max_cll); + return AVERROR(EINVAL); + } + av_log(avctx, AV_LOG_DEBUG, "Set max_cll=%s.\n", ctx->max_cll); + } + + if (ctx->master_display != 0) { + if (ctx->api->param_parse(ctx->params, "master-display", ctx->master_display) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid master_display: %s.\n", ctx->master_display); + return AVERROR(EINVAL); + } + av_log(avctx, AV_LOG_DEBUG, "Set master_display=%s.\n", ctx->master_display); + } + + if (ctx->bframes >= 0) { + char bframes[20]; + + snprintf(bframes, sizeof(bframes), "%d", ctx->bframes); + if (ctx->api->param_parse(ctx->params, "bframes", bframes) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid bframes: %d.\n", ctx->bframes); + return AVERROR(EINVAL); + } + av_log(avctx, AV_LOG_DEBUG, "Set bframes=%d.\n", ctx->bframes); + } + ctx->params->rc.vbvBufferSize = avctx->rc_buffer_size / 1000; ctx->params->rc.vbvMaxBitrate = avctx->rc_max_rate / 1000; @@ -657,6 +687,9 @@ static av_cold void libx265_encode_init_csp(AVCodec *codec) static const AVOption options[] = { { "crf", "set the x265 crf", OFFSET(crf), AV_OPT_TYPE_FLOAT, { .dbl = -1 }, -1, FLT_MAX, VE }, { "qp", "set the x265 qp", OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "max-cll", "set the x265 max cll,max fall", OFFSET(max_cll), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "master-display", "set the x265 master display", OFFSET(master_display), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "bframes", "set max number of consecutive bframes", OFFSET(bframes), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0, VE }, { "forced-idr", "if forcing keyframes, force them as IDR frames", OFFSET(forced_idr),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index b09ddbe0fa085..a52d1b26e67a0 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -280,7 +280,7 @@ static av_cold int nvenc_load_libraries(AVCodecContext *avctx) if (err != NV_ENC_SUCCESS) return nvenc_print_error(avctx, err, "Failed to query nvenc max version"); - av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf); + av_log(avctx, AV_LOG_INFO, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf); if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) > nvenc_max_ver) { av_log(avctx, AV_LOG_ERROR, "Driver does not support the required nvenc API version. " diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 56708c02410ef..b39403ea5bd55 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1849,12 +1849,22 @@ typedef struct AVFormatContext { */ int max_streams; + /* Special for avpipe, holds out_handler */ + void *avpipe_opaque; /** * Skip duration calcuation in estimate_timings_from_pts. * - encoding: unused * - decoding: set by user */ int skip_estimate_duration_from_pts; + /* + * Keep track of min and max of frame duration and calculate the following: + * frame_duration_variation = (max_frame_duration - min_frame_duration) * 2; + * frame_duration_variation will be used to cut ABR dash/hls segments. + */ + int64_t prev_pts; + int64_t min_frame_duration; + int64_t max_frame_duration; /** * Maximum number of packets that can be probed diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 81a5c2b452645..42ca768f0c414 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -24,13 +24,20 @@ #if HAVE_UNISTD_H #include #endif +#if CONFIG_GCRYPT +#include +#elif CONFIG_OPENSSL +#include +#endif +#include "libavutil/aes.h" #include "libavutil/avassert.h" #include "libavutil/avutil.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/random_seed.h" #include "libavutil/parseutils.h" #include "libavutil/rational.h" #include "libavutil/time.h" @@ -51,6 +58,10 @@ #include "vpcc.h" #include "dash.h" +static const int BLOCKSIZE = 16; +static const int KEYSIZE = 16; +static const char AES_KEY_OUT_PATH[] = "key.bin"; + typedef enum { SEGMENT_TYPE_AUTO = 0, SEGMENT_TYPE_MP4, @@ -138,6 +149,13 @@ typedef struct OutputStream { int64_t gop_size; AVRational sar; int coding_dependency; + struct AVAES *aes_context; + int aes_encrypt; + uint8_t aes_iv[KEYSIZE]; + uint8_t aes_pad[BLOCKSIZE]; + int aes_pad_len; + uint8_t *aes_write_buf; + unsigned int aes_write_buf_size; } OutputStream; typedef struct DASHContext { @@ -199,6 +217,24 @@ typedef struct DASHContext { AVRational min_playback_rate; AVRational max_playback_rate; int64_t update_period; + + int64_t seg_duration_ts; + int64_t start_fragment_index; + int64_t frame_duration_ts; + int start_segment; + + // Pass-through options to movenc -PTT + char *encryption_scheme_str; + uint8_t *encryption_key; + uint8_t *encryption_kid; + uint8_t *encryption_iv; + + int aes_encrypt; + uint8_t aes_iv[KEYSIZE]; + char *aes_iv_hex; + uint8_t aes_key[KEYSIZE]; + char *aes_key_hex; + char *aes_key_url; } DASHContext; static struct codec_string { @@ -223,6 +259,69 @@ static struct format_string { { 0, NULL } }; +static int aes_init(DASHContext *c, OutputStream *os) { + if (!c->aes_encrypt) return 0; + av_assert0(os->aes_context == NULL); + int ret = 0; + if ((os->aes_context = av_aes_alloc()) == NULL) + return AVERROR(ENOMEM); + if ((ret = av_aes_init(os->aes_context, c->aes_key, BLOCKSIZE * 8, 0)) < 0) + return ret; + os->aes_encrypt = 1; + memcpy(os->aes_iv, c->aes_iv, sizeof(os->aes_iv)); + return 0; +} + +static void aes_free(OutputStream *os) { + if (!os->aes_encrypt) return; + if (os->aes_context) { + uint8_t out_buf[BLOCKSIZE]; + int pad = BLOCKSIZE - os->aes_pad_len; + + memset(&os->aes_pad[os->aes_pad_len], pad, pad); + av_aes_crypt(os->aes_context, out_buf, os->aes_pad, 1, os->aes_iv, 0); + avio_write(os->out, out_buf, BLOCKSIZE); + } + av_freep(&os->aes_context); + av_freep(&os->aes_write_buf); + os->aes_encrypt = 0; + os->aes_pad_len = 0; + os->aes_write_buf_size = 0; +} + +static int dashenc_avio_write(OutputStream *os, const unsigned char *buf, int size) { + if (!os->aes_encrypt) { + avio_write(os->out, buf, size); + return size; + } + + int total_size = size + os->aes_pad_len; + int pad_len = total_size % BLOCKSIZE; + int out_size = total_size - pad_len; + int blocks = out_size / BLOCKSIZE; + + if (out_size) { + av_fast_malloc(&os->aes_write_buf, &os->aes_write_buf_size, out_size); + if (!os->aes_write_buf) + return AVERROR(ENOMEM); + if (os->aes_pad_len) { + memcpy(&os->aes_pad[os->aes_pad_len], buf, BLOCKSIZE - os->aes_pad_len); + av_aes_crypt(os->aes_context, os->aes_write_buf, os->aes_pad, 1, os->aes_iv, 0); + blocks--; + } + av_aes_crypt(os->aes_context, + &os->aes_write_buf[os->aes_pad_len ? BLOCKSIZE : 0], + &buf[os->aes_pad_len ? BLOCKSIZE - os->aes_pad_len : 0], + blocks, os->aes_iv, 0); + avio_write(os->out, os->aes_write_buf, out_size); + memcpy(os->aes_pad, &buf[size - pad_len], pad_len); + } else { + memcpy(&os->aes_pad[os->aes_pad_len], buf, size); + } + os->aes_pad_len = pad_len; + return size; +} + static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options) { DASHContext *c = s->priv_data; @@ -471,7 +570,7 @@ static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length) *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer); os->ctx->pb = NULL; if (os->out) - avio_write(os->out, buffer + os->written_len, *range_length - os->written_len); + dashenc_avio_write(os, buffer + os->written_len, *range_length - os->written_len); os->written_len = 0; av_free(buffer); @@ -524,8 +623,9 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, AVDictionary *http_opts = NULL; int target_duration = 0; int ret = 0; - const char *proto = avio_find_protocol_name(c->dirname); - int use_rename = proto && !strcmp(proto, "file"); + //const char *proto = avio_find_protocol_name(c->dirname); + //int use_rename = proto && !strcmp(proto, "file"); + int use_rename = 0; int i, start_index, start_number; double prog_date_time = 0; @@ -557,6 +657,13 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration, start_number, PLAYLIST_TYPE_NONE, 0); + if (c->aes_encrypt) { + avio_printf(c->m3u8_out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", c->aes_key_url); + if (*c->aes_iv_hex) + avio_printf(c->m3u8_out, ",IV=0x%s", c->aes_iv_hex); + avio_printf(c->m3u8_out, "\n"); + } + ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file, os->init_range_length, os->init_start_pos); @@ -606,6 +713,7 @@ static int flush_init_segment(AVFormatContext *s, OutputStream *os) if (!c->single_file) { char filename[1024]; snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile); + aes_free(os); dashenc_io_close(s, &os->out, filename); } return 0; @@ -645,6 +753,7 @@ static void dash_free(AVFormatContext *s) av_freep(&os->single_file_name); av_freep(&os->init_seg_name); av_freep(&os->media_seg_name); + aes_free(os); } av_freep(&c->streams); @@ -1156,6 +1265,8 @@ static int write_manifest(AVFormatContext *s, int final) if (!use_rename && !warned_non_file++) av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n"); + use_rename = 0; // PENDING(SSS) need protocol 'buf' + snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url); set_http_options(&opts, c); ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts); @@ -1357,6 +1468,85 @@ static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const ch return 0; } +static int randomize(uint8_t *buf, int len) +{ +#if CONFIG_GCRYPT + gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM); + return 0; +#elif CONFIG_OPENSSL + if (RAND_bytes(buf, len)) + return 0; +#else + for (int i = 0; i < len; i++) { + buf[i] = av_get_random_seed(); + } + return 0; +#endif + return AVERROR(EINVAL); +} + +// Compare to hlsenc.c::do_encrypt() -PTT +static int init_crypto(AVFormatContext *s) +{ + DASHContext *c = s->priv_data; + int ret = 0; + int write_key_file = 0; + + const int iv_len = sizeof(c->aes_iv); + const int iv_hex_len = iv_len * 2; + if (!c->aes_iv_hex || strlen(c->aes_iv_hex) == 0) { + if ((ret = randomize(c->aes_iv, iv_len)) < 0) { + av_log(s, AV_LOG_ERROR, "Failed to generate an AES IV\n"); + return ret; + } + c->aes_iv_hex = av_mallocz(iv_hex_len + 1); + ff_data_to_hex(c->aes_iv_hex, c->aes_iv, iv_len, 0); + c->aes_iv_hex[iv_hex_len] = '\0'; + } else { + if (strlen(c->aes_iv_hex) != iv_hex_len) { + av_log(s, AV_LOG_ERROR, "The AES IV must be 32 hex characters\n"); + return ret; + } + ff_hex_to_data(c->aes_iv, c->aes_iv_hex); + } + + const int key_len = sizeof(c->aes_key); + const int key_hex_len = key_len * 2; + if (!c->aes_key_hex || strlen(c->aes_key_hex) == 0) { + if ((ret = randomize(c->aes_key, key_len)) < 0) { + av_log(s, AV_LOG_ERROR, "Failed to generate an AES key\n"); + return ret; + } + c->aes_key_hex = av_mallocz(key_hex_len + 1); + ff_data_to_hex(c->aes_key_hex, c->aes_key, key_len, 0); + c->aes_key_hex[key_hex_len] = '\0'; + write_key_file = 1; + } else { + if (strlen(c->aes_key_hex) != key_hex_len) { + av_log(s, AV_LOG_ERROR, "The AES key must be 32 hex characters\n"); + return ret; + } + ff_hex_to_data(c->aes_key, c->aes_key_hex); + } + + if (!c->aes_key_url || strlen(c->aes_key_url) == 0) { + c->aes_key_url = av_mallocz(sizeof(AES_KEY_OUT_PATH)); + av_strlcpy(c->aes_key_url, AES_KEY_OUT_PATH, sizeof(AES_KEY_OUT_PATH)); + write_key_file = 1; + } + + if (write_key_file) { + AVIOContext *pb = NULL; + if ((ret = s->io_open(s, &pb, AES_KEY_OUT_PATH, AVIO_FLAG_WRITE, NULL)) < 0) + return ret; + avio_seek(pb, 0, SEEK_CUR); + avio_write(pb, c->aes_key, KEYSIZE); + ff_format_io_close(s, &pb); + } + + return 0; +} + static int dash_init(AVFormatContext *s) { DASHContext *c = s->priv_data; @@ -1370,6 +1560,10 @@ static int dash_init(AVFormatContext *s) if (c->single_file) c->use_template = 0; + s->min_frame_duration = INT64_MAX; + s->max_frame_duration = INT64_MIN; + s->prev_pts = AV_NOPTS_VALUE; + if (!c->profile) { av_log(s, AV_LOG_ERROR, "At least one profile must be enabled.\n"); return AVERROR(EINVAL); @@ -1474,6 +1668,10 @@ static int dash_init(AVFormatContext *s) if ((ret = init_segment_types(s)) < 0) return ret; + if (c->aes_encrypt) { + if ((ret = init_crypto(s)) < 0) return ret; + } + for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; AdaptationSet *as = &c->as[os->as_idx - 1]; @@ -1481,6 +1679,7 @@ static int dash_init(AVFormatContext *s) AVStream *st; AVDictionary *opts = NULL; char filename[1024]; + AVRational time_base; os->bit_rate = s->streams[i]->codecpar->bit_rate; if (!os->bit_rate) { @@ -1582,6 +1781,8 @@ static int dash_init(AVFormatContext *s) av_dict_free(&opts); if (ret < 0) return ret; + if ((ret = aes_init(c, os)) != 0) + return ret; os->init_start_pos = 0; av_dict_copy(&opts, c->format_options, 0); @@ -1625,10 +1826,39 @@ static int dash_init(AVFormatContext *s) // skip_trailer : Avoids growing memory usage with time av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND); else { - if (c->global_sidx) - av_dict_set(&opts, "movflags", "+dash+delay_moov+global_sidx+skip_trailer", AV_DICT_APPEND); - else - av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_trailer", AV_DICT_APPEND); + if (c->global_sidx) { + if (c->start_segment > 1) { + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+frag_discont+skip_trailer", 0); + } else { + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_trailer", 0); + } + } else { + if (c->start_segment > 1) { + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+frag_discont", 0); + } else { + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0); + } + } + } + + if (c->start_fragment_index > 1) { + char start_fragment_index_str[128]; + (void)sprintf(start_fragment_index_str, "%" PRId64, c->start_fragment_index); + av_dict_set(&opts, "fragment_index", start_fragment_index_str, 0); + av_log(s, AV_LOG_INFO, "Fragment index=%s", start_fragment_index_str); + } + + if (c->encryption_scheme_str != NULL) { + av_dict_set(&opts, "encryption_scheme", c->encryption_scheme_str, 0); + } + if (c->encryption_key != NULL) { + av_dict_set(&opts, "encryption_key", c->encryption_key, 0); + } + if (c->encryption_kid != NULL) { + av_dict_set(&opts, "encryption_kid", c->encryption_kid, 0); + } + if (c->encryption_iv != NULL) { + av_dict_set(&opts, "encryption_iv", c->encryption_iv, 0); } if (os->frag_type == FRAG_TYPE_EVERY_FRAME) av_dict_set(&opts, "movflags", "+frag_every_frame", AV_DICT_APPEND); @@ -1645,7 +1875,18 @@ static int dash_init(AVFormatContext *s) av_dict_set_int(&opts, "dash_track_number", i + 1, 0); av_dict_set_int(&opts, "live", 1, 0); } + time_base = st->time_base; + /* avformat_init_output() might change stream time_base if time_base < 10000 */ ret = avformat_init_output(ctx, &opts); + /* + * Basically the problem is when time_base < 10000, then ffmpeg doubles the timebase in a loop (in movenc.c) + * until it becomes bigger than 10000 (i.e 600 -> 19200). + * This change in the time_base causes a divide by zero in dash_flush() function. + * To avoid this situation, it is needed to rescale seg_duration_ts too. + */ + if (time_base.den != st->time_base.den) { + c->seg_duration_ts *= st->time_base.den/(time_base.den*st->time_base.num); + } av_dict_free(&opts); if (ret < 0) return ret; @@ -1694,12 +1935,22 @@ static int dash_init(AVFormatContext *s) c->has_video = 1; } + /* Calculate the seg_duration in time_base units */ +#if 0 + c->seg_duration_ts = + (c->seg_duration * s->streams[i]->time_base.den) / + (1000000 * s->streams[i]->time_base.num); + av_log(s, AV_LOG_DEBUG, "HAPPY seg_duration_ts=%lld mod=%lld\n", c->seg_duration_ts, + c->seg_duration * s->streams[i]->time_base.den % (1000000 * s->streams[i]->time_base.num)); +#endif + av_log(s, AV_LOG_DEBUG, "seg_duration_ts=%"PRId64"\n", c->seg_duration_ts); + set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str, sizeof(os->codec_str)); os->first_pts = AV_NOPTS_VALUE; os->max_pts = AV_NOPTS_VALUE; os->last_dts = AV_NOPTS_VALUE; - os->segment_index = 1; + os->segment_index = c->start_segment; if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) c->nr_of_streams_to_flush++; @@ -1904,6 +2155,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream) const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); + use_rename = 0; + int cur_flush_segment_index = 0, next_exp_index = -1; if (stream >= 0) { cur_flush_segment_index = c->streams[stream].segment_index; @@ -1955,6 +2208,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (c->single_file) { find_index_range(s, os->full_path, os->pos, &index_length); } else { + aes_free(os); dashenc_io_close(s, &os->out, os->temp_path); if (use_rename) { @@ -1967,6 +2221,20 @@ static int dash_flush(AVFormatContext *s, int final, int stream) duration = av_rescale_q(os->max_pts - os->start_pts, st->time_base, AV_TIME_BASE_Q); os->last_duration = FFMAX(os->last_duration, duration); + if (!os->muxer_overhead) { + if (av_rescale_q(os->max_pts - os->start_pts, st->time_base, AV_TIME_BASE_Q) != 0) + os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) * + 8 * AV_TIME_BASE) / + av_rescale_q(os->max_pts - os->start_pts, + st->time_base, AV_TIME_BASE_Q); + else + /* This (else) should not happen anymore after rescaling seg_duration_ts. + * But just to be on the safe side I will keep this. + */ + os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) * + 8 * AV_TIME_BASE) * st->time_base.num / st->time_base.den; + } + if (!os->muxer_overhead && os->max_pts > os->start_pts) os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) * 8 * AV_TIME_BASE) / duration; @@ -2133,6 +2401,47 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) seg_end_duration = os->seg_duration; } + if (s->prev_pts != AV_NOPTS_VALUE) { + int64_t delta = pkt->pts - s->prev_pts; + delta = delta > 0 ? delta : (-1)*delta; + if (delta < s->min_frame_duration) + s->min_frame_duration = delta; + if (delta > s->max_frame_duration) + s->max_frame_duration = delta; + } + + int64_t frame_duration_variation = 0; + + if (s->prev_pts != AV_NOPTS_VALUE) + frame_duration_variation = (s->max_frame_duration - s->min_frame_duration) * 2; + + /* + * This is just for backward compatibility and not break anything. + * (we used to set frame_duration_variation = 1) + */ + if (frame_duration_variation == 0) + frame_duration_variation = 1; + + s->prev_pts = pkt->pts; + +#if 0 + av_log(s, AV_LOG_INFO, "dash_write_packet is_key=%d pts=%"PRId64" duration=%"PRId64" start_pts=%"PRId64 + " max_pts=%"PRId64" elapsed_duration=%"PRId64" seg_duration_ts=%"PRId64" frame_duration_variation=%"PRId64 + " min_frame_duration=%"PRId64" max_frame_duration=%"PRId64, + pkt->flags & AV_PKT_FLAG_KEY, pkt->pts, pkt->duration, os->start_pts, os->max_pts, + elapsed_duration, c->seg_duration_ts, frame_duration_variation, + s->min_frame_duration, s->max_frame_duration); +#endif + /* + * For the rare case frame duration is not a timebase integer (for example 1501.5) + * or if frame duration is not constant we need to accommodate for the variation. + * When frame duration is fractional, the variation is always 1 + * In another case, like PBS live stream, the packet duration is variable (for example 2970, or 3060). + * In this case, the cutting might not happen in exact PTS that is expected. Therefore, cut within a window + * or interval around expected PTS. + */ + + if (os->parser && (os->frag_type == FRAG_TYPE_PFRAMES || as->trick_idx >= 0)) { @@ -2172,6 +2481,11 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) sizeof(os->producer_reference_time_str), os->producer_reference_time.wallclock); + av_log(s, AV_LOG_DEBUG, "dash_write_packet end of segment pts=%"PRId64" duration=%"PRId64" start_pts=%"PRId64 + " max_pts=%"PRId64" elapsed_duration=%"PRId64" seg_duration_ts=%"PRId64, + pkt->pts, pkt->duration, os->start_pts, os->max_pts, elapsed_duration, c->seg_duration_ts); + + if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0) return ret; } @@ -2231,8 +2545,10 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) //open the output context when the first frame of a segment is ready if (!c->single_file && os->packets_written == 1) { AVDictionary *opts = NULL; + char stream_index[10]; const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); + use_rename = 0; // PENDING(SSS) make proto 'buf' if (os->segment_type == SEGMENT_TYPE_MP4) write_styp(os->ctx->pb); os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0'; @@ -2249,6 +2565,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { return handle_io_open_error(s, ret, os->temp_path); } + if ((ret = aes_init(c, os)) != 0) + return ret; if (c->lhls) { char *prefetch_url = use_rename ? NULL : os->filename; write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url); @@ -2262,7 +2580,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) avio_flush(os->ctx->pb); len = avio_get_dyn_buf (os->ctx->pb, &buf); if (os->out) { - avio_write(os->out, buf + os->written_len, len - os->written_len); + dashenc_avio_write(os, buf + os->written_len, len - os->written_len); avio_flush(os->out); } os->written_len = len; @@ -2344,6 +2662,9 @@ static const AVOption options[] = { { "min_seg_duration", "minimum segment duration (in microseconds) (will be deprecated)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E }, #endif { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E }, + { "seg_duration_ts", "segment duration timebase", OFFSET(seg_duration_ts), AV_OPT_TYPE_INT, { .i64 = 48048 }, 0, INT_MAX, E }, + { "start_fragment_index", "starting frame sequence for fragmented mp4", OFFSET(start_fragment_index), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E }, + { "frame_duration_ts", "frame duration timebase", OFFSET(frame_duration_ts), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E }, { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E }, { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, "frag_type"}, { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"}, @@ -2374,6 +2695,15 @@ static const AVOption options[] = { { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"}, { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "start_segment", "Specify the index of the first segment (which by default is 1)", OFFSET(start_segment), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, E }, + { "encryption_scheme", "Configures the Common Encryption scheme, allowed values are none, cenc-aes-ctr, cenc-aes-cbc-pattern", OFFSET(encryption_scheme_str), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "encryption_key", "The media encryption key (hex)", OFFSET(encryption_key), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "encryption_kid", "The media encryption key identifier (hex)", OFFSET(encryption_kid), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "encryption_iv", "Specify the media encryption iv (hex)", OFFSET(encryption_iv), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "hls_enc", "enable AES128 encryption support", OFFSET(aes_encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E}, + { "hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(aes_key_hex), AV_OPT_TYPE_STRING, .flags = E}, + { "hls_enc_key_url", "url to access the key to decrypt the segments", OFFSET(aes_key_url), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + { "hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(aes_iv_hex), AV_OPT_TYPE_STRING, .flags = E}, { "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, { "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, E}, diff --git a/libavformat/isom.h b/libavformat/isom.h index 5a6d504090741..c547e26fd3c92 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -111,6 +111,12 @@ typedef struct MOVSbgp { unsigned int index; } MOVSbgp; +typedef enum { + MOV_ENC_NONE = 0, + MOV_ENC_CENC_AES_CTR, + MOV_ENC_CENC_AES_CBC_PATTERN +} MOVEncryptionScheme; + typedef struct MOVEncryptionIndex { // Individual encrypted samples. If there are no elements, then the default // settings will be used. diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 2cd5773dc5ea9..1bf8a2e7a43a9 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -98,9 +98,10 @@ static const AVOption options[] = { { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM}, { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, - { "encryption_scheme", "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext, encryption_scheme_str), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "encryption_scheme", "Configures the Common Encryption scheme, allowed values are none, cenc-aes-ctr, cenc-aes-cbc-pattern", offsetof(MOVMuxContext, encryption_scheme_str), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "encryption_iv", "Specify the media encryption iv (hex)", offsetof(MOVMuxContext, encryption_iv), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "write_prft", "Write producer reference time box with specified time source", offsetof(MOVMuxContext, write_prft), AV_OPT_TYPE_INT, {.i64 = MOV_PRFT_NONE}, 0, MOV_PRFT_NB-1, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, @@ -2667,7 +2668,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); mov_write_stco_tag(pb, track); - if (track->cenc.aes_ctr) { + if (track->cenc.encryption_scheme != MOV_ENC_NONE && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) { ff_mov_cenc_write_stbl_atoms(&track->cenc, pb); } if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) { @@ -3393,6 +3394,10 @@ static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext if (track->tref_tag) mov_write_tref_tag(pb, track); + if (track->cenc.encryption_scheme != MOV_ENC_NONE && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) { + ff_mov_cenc_write_senc_tag(&track->cenc, pb, 0); + } + if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0) return ret; if (track->mode == MODE_PSP) @@ -4689,6 +4694,11 @@ static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, } } + if (track->cenc.encryption_scheme != MOV_ENC_NONE) { + ff_mov_cenc_write_senc_tag(&track->cenc, pb, moof_offset); + ff_mov_cenc_write_stbl_atoms(&track->cenc, pb); + } + return update_size(pb, pos); } @@ -5505,6 +5515,8 @@ static int mov_flush_fragment(AVFormatContext *s, int force) avio_write(s->pb, buf, buf_size); av_free(buf); + + ff_mov_cenc_auxiliary_info_reset(&track->cenc); } mov->mdat_size = 0; @@ -5527,12 +5539,15 @@ static int mov_auto_flush_fragment(AVFormatContext *s, int force) return ret; } +#define DTS_THRESHOLD 1 + static int check_pkt(AVFormatContext *s, AVPacket *pkt) { MOVMuxContext *mov = s->priv_data; MOVTrack *trk = &mov->tracks[pkt->stream_index]; int64_t ref; uint64_t duration; + int64_t dts_with_threshold; if (trk->entry) { ref = trk->cluster[trk->entry - 1].dts; @@ -5548,10 +5563,11 @@ static int check_pkt(AVFormatContext *s, AVPacket *pkt) ref -= trk->dts_shift; } - duration = pkt->dts - ref; - if (pkt->dts < ref || duration >= INT_MAX) { - av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range for mov/mp4 format\n", - duration, pkt->dts + dts_with_threshold = pkt->dts + DTS_THRESHOLD; + duration = dts_with_threshold - ref; + if (dts_with_threshold < ref || duration >= INT_MAX) { + av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range %"PRId64" for mov/mp4 format\n", + duration, pkt->dts, ref ); pkt->dts = ref + 1; @@ -5683,8 +5699,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; avio_write(pb, reformatted_data, size); } else { - if (trk->cenc.aes_ctr) { - size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size); + if (trk->cenc.encryption_scheme != MOV_ENC_NONE) { + size = ff_mov_cenc_avc_parse_nal_units(s, &trk->cenc, pb, pkt); if (size < 0) { ret = size; goto err; @@ -5741,15 +5757,14 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } } } else { - if (trk->cenc.aes_ctr) { + if (trk->cenc.encryption_scheme != MOV_ENC_NONE) { if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) { - int nal_size_length = (par->extradata[4] & 0x3) + 1; - ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size); + ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, pb, pkt); } else { ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size); } - if (ret) { + if (ret < 0) { goto err; } } else { @@ -6518,6 +6533,15 @@ static int mov_init(AVFormatContext *s) return AVERROR(EINVAL); } + /* Call io_open call back if pb is NULL (output format is "mp4", and using mp4 muxer) */ + if (!s->pb && s->io_open) { + AVDictionary *opts = NULL; + ret = s->io_open(s, &s->pb, s->url, AVIO_FLAG_WRITE, &opts); + av_dict_free(&opts); + if (ret < 0) + return ret; + } + /* Non-seekable output is ok if using fragmentation. If ism_lookahead * is enabled, we don't support non-seekable output at all. */ if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && @@ -6582,23 +6606,28 @@ static int mov_init(AVFormatContext *s) if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) { if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) { mov->encryption_scheme = MOV_ENC_CENC_AES_CTR; - if (mov->encryption_key_len != AES_CTR_KEY_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n", + av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d; expected %d\n", mov->encryption_key_len, AES_CTR_KEY_SIZE); return AVERROR(EINVAL); } - - if (mov->encryption_kid_len != CENC_KID_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n", - mov->encryption_kid_len, CENC_KID_SIZE); + } else if (strcmp(mov->encryption_scheme_str, "cenc-aes-cbc-pattern") == 0) { + mov->encryption_scheme = MOV_ENC_CENC_AES_CBC_PATTERN; + if (mov->encryption_key_len != 16) { // 9.4.3 of the ISO CENC spec + av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d; expected 16\n", + mov->encryption_key_len); return AVERROR(EINVAL); } } else { - av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n", + av_log(s, AV_LOG_ERROR, "Unsupported encryption scheme %s\n", mov->encryption_scheme_str); return AVERROR(EINVAL); } + if (mov->encryption_kid_len != CENC_KID_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d; expected %d\n", + mov->encryption_kid_len, CENC_KID_SIZE); + return AVERROR(EINVAL); + } } for (i = 0; i < s->nb_streams; i++) { @@ -6754,8 +6783,10 @@ static int mov_init(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, track->timescale); - if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { - ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key, + if (mov->encryption_scheme != MOV_ENC_NONE) { + ret = ff_mov_cenc_init(&track->cenc, track->par, + mov->encryption_scheme, mov->encryption_key, + mov->encryption_iv, mov->encryption_iv_len, track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT); if (ret) return ret; diff --git a/libavformat/movenc.h b/libavformat/movenc.h index cdbc4074c37d0..baa1cbd861a85 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -166,11 +166,6 @@ typedef struct MOVTrack { int is_unaligned_qt_rgb; } MOVTrack; -typedef enum { - MOV_ENC_NONE = 0, - MOV_ENC_CENC_AES_CTR, -} MOVEncryptionScheme; - typedef enum { MOV_PRFT_NONE = 0, MOV_PRFT_SRC_WALLCLOCK, @@ -229,6 +224,8 @@ typedef struct MOVMuxContext { int encryption_key_len; uint8_t *encryption_kid; int encryption_kid_len; + uint8_t *encryption_iv; + int encryption_iv_len; int need_rewrite_extradata; diff --git a/libavformat/movenccenc.c b/libavformat/movenccenc.c index 74f3c4ccfbc99..ea76e39c966cf 100644 --- a/libavformat/movenccenc.c +++ b/libavformat/movenccenc.c @@ -19,10 +19,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "movenccenc.h" -#include "libavutil/intreadwrite.h" +#include "avc.h" #include "avio_internal.h" #include "movenc.h" -#include "avc.h" +#include "libavcodec/h2645_parse.h" +#include "libavcodec/internal.h" +#include "libavutil/aes.h" +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/random_seed.h" + +#define AES_BLOCK_SIZE (16) static int auxiliary_info_alloc_size(MOVMuxCencContext* ctx, int size) { @@ -41,7 +48,7 @@ static int auxiliary_info_alloc_size(MOVMuxCencContext* ctx, int size) } static int auxiliary_info_write(MOVMuxCencContext* ctx, - const uint8_t *buf_in, int size) + const uint8_t *buf_in, int size) { int ret; @@ -83,21 +90,50 @@ static int auxiliary_info_add_subsample(MOVMuxCencContext* ctx, return 0; } +void ff_mov_cenc_auxiliary_info_reset(MOVMuxCencContext* ctx) { + ctx->auxiliary_info_size = 0; + ctx->auxiliary_info_entries = 0; +} + /** * Encrypt the input buffer and write using avio_write + * + * For AES-CBC, the block chain starting with MOVMuxCencContext->aes_cbc_iv is + * wholly contained in this function; i.e. the chain does not span multiple + * calls. */ static void mov_cenc_write_encrypted(MOVMuxCencContext* ctx, AVIOContext *pb, const uint8_t *buf_in, int size) { - uint8_t chunk[4096]; + uint8_t chunk[4000]; const uint8_t* cur_pos = buf_in; int size_left = size; - int cur_size; + int cur_size, block_count, enc_size, remaining_size; + uint8_t aes_cbc_iv[AES_BLOCK_SIZE]; + + /* pattern encryption repeats every 10 blocks */ + av_assert2(sizeof(chunk) % (AES_BLOCK_SIZE * 10) == 0); + + if (ctx->encryption_scheme == MOV_ENC_CENC_AES_CBC_PATTERN) { + /* use constant IV and reset the chain for each sample/subsample */ + memcpy(aes_cbc_iv, ctx->aes_cbc_iv, sizeof(aes_cbc_iv)); + } while (size_left > 0) { - cur_size = FFMIN(size_left, sizeof(chunk)); - av_aes_ctr_crypt(ctx->aes_ctr, chunk, cur_pos, cur_size); - avio_write(pb, chunk, cur_size); + cur_size = FFMIN((unsigned int)size_left, sizeof(chunk)); + if (ctx->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + av_aes_ctr_crypt(ctx->aes_ctr, chunk, cur_pos, cur_size); + avio_write(pb, chunk, cur_size); + } else { /* MOV_ENC_CENC_AES_CBC_PATTERN */ + /* remaining data smaller than a full block remains unencrypted */ + block_count = cur_size / AES_BLOCK_SIZE; + enc_size = block_count * AES_BLOCK_SIZE; + remaining_size = cur_size - enc_size; + /* same call for both pattern and full sample encryption */ + av_aes_crypt(ctx->aes_cbc, chunk, cur_pos, block_count, aes_cbc_iv, 0); + avio_write(pb, chunk, enc_size); + avio_write(pb, cur_pos + enc_size, remaining_size); + } cur_pos += cur_size; size_left -= cur_size; } @@ -108,14 +144,21 @@ static void mov_cenc_write_encrypted(MOVMuxCencContext* ctx, AVIOContext *pb, */ static int mov_cenc_start_packet(MOVMuxCencContext* ctx) { - int ret; - - /* write the iv */ - ret = auxiliary_info_write(ctx, av_aes_ctr_get_iv(ctx->aes_ctr), AES_CTR_IV_SIZE); - if (ret) { - return ret; + int ret = 0; + + /** + * write the iv + * + * omit for cbcs - the per-sample iv is zero when using a constant iv + */ + if (ctx->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + ret = auxiliary_info_write(ctx, av_aes_ctr_get_iv(ctx->aes_ctr), AES_CTR_IV_SIZE); + if (ret) { + return ret; + } } + /* subsample clear/protected data counts are not needed for full sample encryption */ if (!ctx->use_subsamples) { return 0; } @@ -137,15 +180,24 @@ static int mov_cenc_start_packet(MOVMuxCencContext* ctx) static int mov_cenc_end_packet(MOVMuxCencContext* ctx) { size_t new_alloc_size; - - av_aes_ctr_increment_iv(ctx->aes_ctr); - - if (!ctx->use_subsamples) { - ctx->auxiliary_info_entries++; - return 0; + size_t sample_iv_size; + + if (ctx->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + sample_iv_size = AES_CTR_IV_SIZE; + av_aes_ctr_increment_iv(ctx->aes_ctr); + if (!ctx->use_subsamples) { + ctx->auxiliary_info_entries++; + return 0; + } + } else { /* MOV_ENC_CENC_AES_CBC_PATTERN */ + sample_iv_size = 0; /* constant iv */ + if (!ctx->use_subsamples) { + /* no aux info needed */ + return 0; + } } - /* add the auxiliary info entry size*/ + /* add the auxiliary info entry size */ if (ctx->auxiliary_info_entries >= ctx->auxiliary_info_sizes_alloc_size) { new_alloc_size = ctx->auxiliary_info_entries * 2 + 1; if (av_reallocp(&ctx->auxiliary_info_sizes, new_alloc_size)) { @@ -155,10 +207,10 @@ static int mov_cenc_end_packet(MOVMuxCencContext* ctx) ctx->auxiliary_info_sizes_alloc_size = new_alloc_size; } ctx->auxiliary_info_sizes[ctx->auxiliary_info_entries] = - AES_CTR_IV_SIZE + ctx->auxiliary_info_size - ctx->auxiliary_info_subsample_start; + sample_iv_size + ctx->auxiliary_info_size - ctx->auxiliary_info_subsample_start; ctx->auxiliary_info_entries++; - /* update the subsample count*/ + /* update the subsample count */ AV_WB16(ctx->auxiliary_info + ctx->auxiliary_info_subsample_start, ctx->subsample_count); return 0; @@ -189,36 +241,70 @@ int ff_mov_cenc_write_packet(MOVMuxCencContext* ctx, AVIOContext *pb, return 0; } -int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, - const uint8_t *buf_in, int size) +// TODO refactor with ff_mov_cenc_avc_write_nal_units +int ff_mov_cenc_avc_parse_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, + AVIOContext *pb, AVPacket *pkt) { - const uint8_t *p = buf_in; - const uint8_t *end = p + size; + int encsize, nalsize, naltype, ret, slice_header_len; + int clear_bytes = 0; + int encrypted_bytes = 0; + int nal_index = 0; + int size = 0; + const uint8_t *start = pkt->data; + const uint8_t *end = start + pkt->size; const uint8_t *nal_start, *nal_end; - int ret; ret = mov_cenc_start_packet(ctx); if (ret) { return ret; } - size = 0; - nal_start = ff_avc_find_startcode(p, end); + uint8_t *parsed_buf_out; + int parsed_buf_out_size; + av_parser_parse2(ctx->parser, ctx->parser_avctx, &parsed_buf_out, + &parsed_buf_out_size, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); + H2645NAL* nals = (H2645NAL*) avpriv_h264_extract_nals(ctx->parser); + + nal_start = ff_avc_find_startcode(start, end); for (;;) { while (nal_start < end && !*(nal_start++)); - if (nal_start == end) + if (nal_start == end) { + if (ctx->subsample_count == 0) { + /* must write at least one subsample before exiting */ + auxiliary_info_add_subsample(ctx, clear_bytes, encrypted_bytes); + } break; + } nal_end = ff_avc_find_startcode(nal_start, end); - - avio_wb32(pb, nal_end - nal_start); - avio_w8(pb, *nal_start); - mov_cenc_write_encrypted(ctx, pb, nal_start + 1, nal_end - nal_start - 1); - - auxiliary_info_add_subsample(ctx, 5, nal_end - nal_start - 1); + nalsize = nal_end - nal_start; + avio_wb32(pb, nalsize); + clear_bytes += 4; + + naltype = *nal_start & 0x1f; + int header_bits = nals[nal_index].slice_header_len_bits; + slice_header_len = (header_bits + 7) / 8; + if ((naltype == 1 || naltype == 5) && + nalsize >= slice_header_len + AES_BLOCK_SIZE) + { + avio_write(pb, nal_start, slice_header_len); + clear_bytes += slice_header_len; + + encsize = nalsize - slice_header_len; + mov_cenc_write_encrypted(ctx, pb, nal_start + slice_header_len, encsize); + encrypted_bytes += encsize; + + auxiliary_info_add_subsample(ctx, clear_bytes, encrypted_bytes); + clear_bytes = 0; + encrypted_bytes = 0; + } else { + avio_write(pb, nal_start, nalsize); + clear_bytes += nalsize; + } size += 4 + nal_end - nal_start; nal_start = nal_end; + nal_index++; } ret = mov_cenc_end_packet(ctx); @@ -229,45 +315,85 @@ int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, return size; } +// TODO combine with ff_mov_cenc_avc_parse_nal_units int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, - int nal_length_size, AVIOContext *pb, const uint8_t *buf_in, int size) + AVIOContext *pb, AVPacket *pkt) { - int nalsize; - int ret; - int j; + int encsize, j, nalsize, naltype, ret, slice_header_len; + int clear_bytes = 0; + int encrypted_bytes = 0; + int nal_index = 0; + int size = 0; + const uint8_t *buf_in = pkt->data; + int remaining = pkt->size; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + const int nal_length_size = (par->extradata[4] & 0x3) + 1; ret = mov_cenc_start_packet(ctx); if (ret) { return ret; } - while (size > 0) { + uint8_t *parsed_buf_out; + int parsed_buf_out_size; + av_parser_parse2(ctx->parser, ctx->parser_avctx, &parsed_buf_out, + &parsed_buf_out_size, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); + H2645NAL* nals = (H2645NAL*)avpriv_h264_extract_nals(ctx->parser); + + // TODO maybe use parsed info above to not parse again below + while (remaining > 0) { /* parse the nal size */ - if (size < nal_length_size + 1) { - av_log(s, AV_LOG_ERROR, "CENC-AVC: remaining size %d smaller than nal length+type %d\n", - size, nal_length_size + 1); + if (remaining < nal_length_size) { + av_log(s, AV_LOG_ERROR, "CENC-AVC: remaining size %d smaller than nal length header %d\n", remaining, nal_length_size); return -1; } - avio_write(pb, buf_in, nal_length_size + 1); - + avio_write(pb, buf_in, nal_length_size); nalsize = 0; for (j = 0; j < nal_length_size; j++) { nalsize = (nalsize << 8) | *buf_in++; } - size -= nal_length_size; + clear_bytes += nal_length_size; + remaining -= nal_length_size; - /* encrypt the nal body */ - if (nalsize <= 0 || nalsize > size) { - av_log(s, AV_LOG_ERROR, "CENC-AVC: nal size %d remaining %d\n", nalsize, size); + if (nalsize <= 0 || nalsize > remaining) { + av_log(s, AV_LOG_ERROR, "CENC-AVC: nal size %d, remaining %d\n", nalsize, remaining); return -1; } - mov_cenc_write_encrypted(ctx, pb, buf_in + 1, nalsize - 1); + /** + * Only encrypt slice data 1 H264_NAL_SLICE and 5 H264_NAL_IDR_SLICE. + * Leave other nal types and VCL (video) slice headers clear, per Apple + * MPEG-2 HLS encryption and CENC specs. + */ + naltype = *buf_in & 0x1f; + int header_bits = nals[nal_index].slice_header_len_bits; + slice_header_len = (header_bits + 7) / 8; + if ((naltype == 1 || naltype == 5) && + nalsize >= slice_header_len + AES_BLOCK_SIZE) + { + avio_write(pb, buf_in, slice_header_len); + clear_bytes += slice_header_len; + + encsize = nalsize - slice_header_len; + mov_cenc_write_encrypted(ctx, pb, buf_in + slice_header_len, encsize); + encrypted_bytes += encsize; + + auxiliary_info_add_subsample(ctx, clear_bytes, encrypted_bytes); + clear_bytes = 0; + encrypted_bytes = 0; + } else { + avio_write(pb, buf_in, nalsize); + clear_bytes += nalsize; + if (remaining - nalsize <= 0 && ctx->subsample_count == 0) { + /* must write at least one subsample before exiting */ + auxiliary_info_add_subsample(ctx, clear_bytes, encrypted_bytes); + } + } + remaining -= nalsize; + size += 4 + nalsize; buf_in += nalsize; - size -= nalsize; - - auxiliary_info_add_subsample(ctx, nal_length_size + 1, nalsize - 1); + nal_index++; } ret = mov_cenc_end_packet(ctx); @@ -275,7 +401,7 @@ int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, return ret; } - return 0; + return size; } /* TODO: reuse this function from movenc.c */ @@ -289,46 +415,63 @@ static int64_t update_size(AVIOContext *pb, int64_t pos) return curpos - pos; } -static int mov_cenc_write_senc_tag(MOVMuxCencContext* ctx, AVIOContext *pb, - int64_t* auxiliary_info_offset) +int ff_mov_cenc_write_senc_tag(MOVMuxCencContext* ctx, AVIOContext *pb, int64_t moof_offset) { - int64_t pos = avio_tell(pb); + int64_t pos; + if (ctx->auxiliary_info_entries == 0) { + return 0; + } + + pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "senc"); avio_wb32(pb, ctx->use_subsamples ? 0x02 : 0); /* version & flags */ avio_wb32(pb, ctx->auxiliary_info_entries); /* entry count */ - *auxiliary_info_offset = avio_tell(pb); + ctx->auxiliary_info_offset = avio_tell(pb) - moof_offset; avio_write(pb, ctx->auxiliary_info, ctx->auxiliary_info_size); return update_size(pb, pos); } -static int mov_cenc_write_saio_tag(AVIOContext *pb, int64_t auxiliary_info_offset) +static int mov_cenc_write_saio_tag(MOVMuxCencContext* ctx, AVIOContext *pb) { - int64_t pos = avio_tell(pb); + int64_t pos; uint8_t version; + if (ctx->auxiliary_info_entries == 0) { + return 0; + } + + pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "saio"); - version = auxiliary_info_offset > 0xffffffff ? 1 : 0; + version = ctx->auxiliary_info_offset > 0xffffffff ? 1 : 0; avio_w8(pb, version); avio_wb24(pb, 0); /* flags */ avio_wb32(pb, 1); /* entry count */ if (version) { - avio_wb64(pb, auxiliary_info_offset); + avio_wb64(pb, ctx->auxiliary_info_offset); } else { - avio_wb32(pb, auxiliary_info_offset); + avio_wb32(pb, ctx->auxiliary_info_offset); } return update_size(pb, pos); } static int mov_cenc_write_saiz_tag(MOVMuxCencContext* ctx, AVIOContext *pb) { - int64_t pos = avio_tell(pb); + int64_t pos; + /* constant iv for cbcs, so sample iv is always zero */ + uint8_t iv_size = ctx->encryption_scheme == MOV_ENC_CENC_AES_CTR ? AES_CTR_IV_SIZE : 0; + + if (ctx->auxiliary_info_entries == 0) { + return 0; + } + + pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "saiz"); avio_wb32(pb, 0); /* version & flags */ - avio_w8(pb, ctx->use_subsamples ? 0 : AES_CTR_IV_SIZE); /* default size*/ + avio_w8(pb, ctx->use_subsamples ? 0 : iv_size); /* default size */ avio_wb32(pb, ctx->auxiliary_info_entries); /* entry count */ if (ctx->use_subsamples) { avio_write(pb, ctx->auxiliary_info_sizes, ctx->auxiliary_info_entries); @@ -338,25 +481,38 @@ static int mov_cenc_write_saiz_tag(MOVMuxCencContext* ctx, AVIOContext *pb) void ff_mov_cenc_write_stbl_atoms(MOVMuxCencContext* ctx, AVIOContext *pb) { - int64_t auxiliary_info_offset; - - mov_cenc_write_senc_tag(ctx, pb, &auxiliary_info_offset); - mov_cenc_write_saio_tag(pb, auxiliary_info_offset); + mov_cenc_write_saio_tag(ctx, pb); mov_cenc_write_saiz_tag(ctx, pb); } -static int mov_cenc_write_schi_tag(AVIOContext *pb, uint8_t* kid) +static int mov_cenc_write_schi_tag(MOVTrack* track, AVIOContext *pb, uint8_t* kid) { + size_t iv_size; int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "schi"); - avio_wb32(pb, 32); /* size */ - ffio_wfourcc(pb, "tenc"); - avio_wb32(pb, 0); /* version & flags */ - avio_wb24(pb, 1); /* is encrypted */ - avio_w8(pb, AES_CTR_IV_SIZE); /* iv size */ - avio_write(pb, kid, CENC_KID_SIZE); + if (track->cenc.encryption_scheme == MOV_ENC_CENC_AES_CTR) { + avio_wb32(pb, 16 + CENC_KID_SIZE); /* size */ + ffio_wfourcc(pb, "tenc"); + avio_wb32(pb, 0); /* version & flags */ + avio_wb24(pb, 1); /* default_isProtected */ + avio_w8(pb, AES_CTR_IV_SIZE); /* default_Per_Sample_IV_Size */ + avio_write(pb, kid, CENC_KID_SIZE); /* default_KID */ + } else { /* MOV_ENC_CENC_AES_CBC_PATTERN */ + iv_size = sizeof(track->cenc.aes_cbc_iv); + avio_wb32(pb, 16 + CENC_KID_SIZE + 1 + iv_size); /* size */ + ffio_wfourcc(pb, "tenc"); + avio_w8(pb, 1); /* version */ + avio_wb24(pb, 0); /* flags */ + avio_w8(pb, 0); /* reserved */ + avio_w8(pb, track->cenc.use_subsamples ? 0x19 : 0); /* default_crypt_byte_block, default_skip_byte_block */ + avio_w8(pb, 1); /* default_isProtected */ + avio_w8(pb, 0); /* default_Per_Sample_IV_Size */ + avio_write(pb, kid, CENC_KID_SIZE); /* default_KID */ + avio_w8(pb, iv_size); /* default_constant_IV_size */ + avio_write(pb, track->cenc.aes_cbc_iv, iv_size); /* default_constant_IV */ + } return update_size(pb, pos); } @@ -364,38 +520,42 @@ static int mov_cenc_write_schi_tag(AVIOContext *pb, uint8_t* kid) int ff_mov_cenc_write_sinf_tag(MOVTrack* track, AVIOContext *pb, uint8_t* kid) { int64_t pos = avio_tell(pb); - avio_wb32(pb, 0); /* size */ + + /* sinf */ + avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "sinf"); /* frma */ - avio_wb32(pb, 12); /* size */ + avio_wb32(pb, 12); /* size */ ffio_wfourcc(pb, "frma"); avio_wl32(pb, track->tag); /* schm */ - avio_wb32(pb, 20); /* size */ + avio_wb32(pb, 20); /* size */ ffio_wfourcc(pb, "schm"); - avio_wb32(pb, 0); /* version & flags */ - ffio_wfourcc(pb, "cenc"); /* scheme type*/ - avio_wb32(pb, 0x10000); /* scheme version */ + avio_wb32(pb, 0); /* version & flags */ + ffio_wfourcc(pb, track->cenc.encryption_scheme == MOV_ENC_CENC_AES_CTR ? + "cenc" : "cbcs"); /* scheme type*/ + avio_wb32(pb, 0x10000); /* scheme version */ /* schi */ - mov_cenc_write_schi_tag(pb, kid); + mov_cenc_write_schi_tag(track, pb, kid); return update_size(pb, pos); } -int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, - int use_subsamples, int bitexact) +static int mov_cenc_ctr_init(MOVMuxCencContext* ctx, uint8_t* key, int bitexact) { int ret; + av_assert0(ctx->aes_ctr == NULL); + ctx->aes_ctr = av_aes_ctr_alloc(); if (!ctx->aes_ctr) { return AVERROR(ENOMEM); } - ret = av_aes_ctr_init(ctx->aes_ctr, encryption_key); + ret = av_aes_ctr_init(ctx->aes_ctr, key); if (ret != 0) { return ret; } @@ -404,14 +564,87 @@ int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, av_aes_ctr_set_random_iv(ctx->aes_ctr); } - ctx->use_subsamples = use_subsamples; + ctx->use_subsamples = 0; return 0; } +static int mov_cenc_cbc_init(MOVMuxCencContext* ctx, uint8_t* key, + uint8_t* iv, int iv_len) +{ + int ret; + uint32_t* iv_part; + + av_assert0(ctx->aes_cbc == NULL); + + ctx->aes_cbc = av_aes_alloc(); + if (!ctx->aes_cbc) { + return AVERROR(ENOMEM); + } + + ret = av_aes_init(ctx->aes_cbc, key, 128, 0); + if (ret != 0) { + return ret; + } + + if (ctx->use_subsamples) { + /* hard-coded to 1 encrypted 9 clear; signaled in the tenc atom */ + av_aes_set_pattern(ctx->aes_cbc, 1, 9); + } + + if (iv_len == AES_BLOCK_SIZE) { + memcpy(ctx->aes_cbc_iv, iv, iv_len); + } else { + iv_part = (uint32_t*)ctx->aes_cbc_iv; + iv_part[0] = av_get_random_seed(); + iv_part[1] = av_get_random_seed(); + iv_part[2] = av_get_random_seed(); + iv_part[3] = av_get_random_seed(); + } + + return 0; +} + +int ff_mov_cenc_init(MOVMuxCencContext* ctx, AVCodecParameters *par, + MOVEncryptionScheme encryption_scheme, uint8_t* key, + uint8_t* iv, int iv_len, + int use_subsamples, int bitexact) +{ + int ret; + + ctx->encryption_scheme = encryption_scheme; + ctx->use_subsamples = use_subsamples; + + ctx->parser = av_parser_init(par->codec_id); + ctx->parser_avctx = avcodec_alloc_context3(NULL); + if (!ctx->parser_avctx) + return AVERROR(ENOMEM); + ret = avcodec_parameters_to_context(ctx->parser_avctx, par); + if (ret < 0) + return ret; + // We only want to parse frame headers + ctx->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + + switch (encryption_scheme) { + case MOV_ENC_CENC_AES_CTR: + return mov_cenc_ctr_init(ctx, key, bitexact); + break; + case MOV_ENC_CENC_AES_CBC_PATTERN: + return mov_cenc_cbc_init(ctx, key, iv, iv_len); + break; + } + return 0; + } + + void ff_mov_cenc_free(MOVMuxCencContext* ctx) { av_aes_ctr_free(ctx->aes_ctr); + if (ctx->encryption_scheme == MOV_ENC_CENC_AES_CBC_PATTERN && ctx->aes_cbc) { + av_freep(&ctx->aes_cbc); + } av_freep(&ctx->auxiliary_info); av_freep(&ctx->auxiliary_info_sizes); + av_parser_close(ctx->parser); + avcodec_free_context(&ctx->parser_avctx); } diff --git a/libavformat/movenccenc.h b/libavformat/movenccenc.h index 6f9e70e9056c2..ad74680ebe5b4 100644 --- a/libavformat/movenccenc.h +++ b/libavformat/movenccenc.h @@ -25,24 +25,32 @@ #include "libavutil/aes_ctr.h" #include "avformat.h" #include "avio.h" +#include "isom.h" #define CENC_KID_SIZE (16) struct MOVTrack; typedef struct { + MOVEncryptionScheme encryption_scheme; + struct AVAES* aes_cbc; + uint8_t aes_cbc_iv[16]; /* AES_BLOCK_SIZE */ struct AVAESCTR* aes_ctr; uint8_t* auxiliary_info; size_t auxiliary_info_size; size_t auxiliary_info_alloc_size; uint32_t auxiliary_info_entries; + uint8_t* auxiliary_info_sizes; + size_t auxiliary_info_sizes_alloc_size; + int64_t auxiliary_info_offset; /* subsample support */ int use_subsamples; uint16_t subsample_count; - size_t auxiliary_info_subsample_start; - uint8_t* auxiliary_info_sizes; - size_t auxiliary_info_sizes_alloc_size; + size_t auxiliary_info_subsample_start; /* location to write subsample_count */ + + AVCodecParserContext *parser; + AVCodecContext *parser_avctx; } MOVMuxCencContext; /** @@ -50,7 +58,10 @@ typedef struct { * @param key encryption key, must have a length of AES_CTR_KEY_SIZE * @param use_subsamples when enabled parts of a packet can be encrypted, otherwise the whole packet is encrypted */ -int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples, int bitexact); +int ff_mov_cenc_init(MOVMuxCencContext* ctx, AVCodecParameters *par, + MOVEncryptionScheme encryption_scheme, uint8_t* encryption_key, + uint8_t* encryption_iv, int encryption_iv_len, + int use_subsamples, int bitexact); /** * Free a CENC context @@ -63,18 +74,32 @@ void ff_mov_cenc_free(MOVMuxCencContext* ctx); int ff_mov_cenc_write_packet(MOVMuxCencContext* ctx, AVIOContext *pb, const uint8_t *buf_in, int size); /** - * Parse AVC NAL units from annex B format, the nal size and type are written in the clear while the body is encrypted + * Parse AVC NAL units from Annex B format. The NAL size and header, and VCL + * slice headers, are written in the clear while the body is encrypted. + * + * Returns bytes written, or < 0 on error + */ +int ff_mov_cenc_avc_parse_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, + AVIOContext *pb, AVPacket *pkt); + +/** + * Write AVC NAL units that are in MP4 format. The NAL size and header, and VCL + * slice headers, are written in the clear while the body is encrypted. + * + * Returns bytes written, or < 0 on error */ -int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, const uint8_t *buf_in, int size); +int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, + AVIOContext *pb, AVPacket *pkt); /** - * Write AVC NAL units that are in MP4 format, the nal size and type are written in the clear while the body is encrypted + * Write the cenc atoms that should reside inside senc + * The senc can reside in either traf or trak */ -int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, int nal_length_size, - AVIOContext *pb, const uint8_t *buf_in, int size); +int ff_mov_cenc_write_senc_tag(MOVMuxCencContext* ctx, AVIOContext *pb, int64_t moof_offset); /** * Write the cenc atoms that should reside inside stbl + * Write the senc first to get the auxiliary_info_offset for saio */ void ff_mov_cenc_write_stbl_atoms(MOVMuxCencContext* ctx, AVIOContext *pb); @@ -83,4 +108,10 @@ void ff_mov_cenc_write_stbl_atoms(MOVMuxCencContext* ctx, AVIOContext *pb); */ int ff_mov_cenc_write_sinf_tag(struct MOVTrack* track, AVIOContext *pb, uint8_t* kid); +/** + * Reset aux info for next moof + */ +void ff_mov_cenc_auxiliary_info_reset(MOVMuxCencContext* ctx); + + #endif /* AVFORMAT_MOVENCCENC_H */ diff --git a/libavformat/segment.c b/libavformat/segment.c index 5265ecaebbe05..124e6b7ea7a8d 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -72,6 +72,8 @@ typedef struct SegmentContext { int segment_idx_wrap; ///< number after which the index wraps int segment_idx_wrap_nb; ///< number of time the index has wraped int segment_count; ///< number of segment files already written + int segment_start_index; + int segment_start_index_initialized; ff_const59 AVOutputFormat *oformat; AVFormatContext *avf; char *format; ///< format to use for output segment files @@ -117,6 +119,8 @@ typedef struct SegmentContext { int break_non_keyframes; int write_empty; + int64_t duration_ts; + int use_rename; char temp_list_filename[1024]; @@ -248,6 +252,17 @@ static int segment_start(AVFormatContext *s, int write_header) if ((err = segment_mux_init(s)) < 0) return err; oc = seg->avf; +#if 0 + /* I added this to have contiguous PTS of an stream but we might not need to go this direction (RM) */ + if (!seg->reset_timestamps) + oc->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; +#endif + } + + // Initialize segment_start_index + if (!seg->segment_start_index_initialized) { + seg->segment_start_index = seg->segment_idx; + seg->segment_start_index_initialized = 1; } seg->segment_idx++; @@ -257,6 +272,7 @@ static int segment_start(AVFormatContext *s, int write_header) if ((err = set_segment_filename(s)) < 0) return err; + oc->avpipe_opaque = s->avpipe_opaque; if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url); return err; @@ -763,6 +779,7 @@ static int seg_init(AVFormatContext *s) if ((ret = set_segment_filename(s)) < 0) return ret; oc = seg->avf; + oc->avpipe_opaque = s->avpipe_opaque; if (seg->write_header_trailer) { if ((ret = s->io_open(s, &oc->pb, @@ -854,6 +871,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) struct tm ti; int64_t usecs; int64_t wrapped_val; + int check_pts = 0; if (!seg->avf || !seg->avf->pb) return AVERROR(EINVAL); @@ -899,13 +917,27 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags & AV_PKT_FLAG_KEY, pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1); + /* If duration_ts was set use it to cut the segment, otherwise use the original time comparison of ffmpeg*/ + if (seg->duration_ts > 0) + check_pts = (pkt->pts >= (seg->cur_entry.index+1-seg->segment_start_index) * seg->duration_ts); + else + check_pts = (av_compare_ts(pkt->pts, st->time_base, end_pts - seg->time_delta, AV_TIME_BASE_Q) >= 0); + +#if 0 + av_log(s, AV_LOG_INFO, "FFF packet stream:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d, check_pts=%d\n", + pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), + av_ts2timestr(pkt->duration, &st->time_base), + pkt->flags & AV_PKT_FLAG_KEY, + pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1, + check_pts); +#endif + if (pkt->stream_index == seg->reference_stream_index && (pkt->flags & AV_PKT_FLAG_KEY || seg->break_non_keyframes) && (seg->segment_frame_count > 0 || seg->write_empty) && (seg->cut_pending || seg->frame_count >= start_frame || - (pkt->pts != AV_NOPTS_VALUE && - av_compare_ts(pkt->pts, st->time_base, - end_pts - seg->time_delta, AV_TIME_BASE_Q) >= 0))) { + (pkt->pts != AV_NOPTS_VALUE && check_pts))) { + /* sanitize end time in case last packet didn't have a defined duration */ if (seg->cur_entry.last_duration == 0) seg->cur_entry.end_time = (double)pkt->pts * av_q2d(st->time_base); @@ -920,6 +952,17 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap * seg->segment_idx_wrap_nb; seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base); seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); + + av_log(s, AV_LOG_INFO, "segment eos stream:%d segment:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d " + "end_pts=%"PRId64" tdelta=%"PRId64" initoff=%"PRId64", rescale=%"PRId64", st->start_time=%"PRId64", cur_seg->start_time=%f\n", + pkt->stream_index, seg->cur_entry.index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), + av_ts2timestr(pkt->duration, &st->time_base), + pkt->flags & AV_PKT_FLAG_KEY, + pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1, + end_pts, seg->time_delta, seg->initial_offset, + av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q), + st->start_time, seg->cur_entry.start_time); + seg->cur_entry.end_time = seg->cur_entry.start_time; if (seg->times || (!seg->frames && !seg->use_clocktime) && seg->write_empty) @@ -934,7 +977,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) } if (seg->segment_frame_count == 0) { - av_log(s, AV_LOG_VERBOSE, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n", + av_log(s, AV_LOG_INFO, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n", seg->avf->url, pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), seg->frame_count); } @@ -948,6 +991,10 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) /* compute new timestamps */ offset = av_rescale_q(seg->initial_offset - (seg->reset_timestamps ? seg->cur_entry.start_pts : 0), AV_TIME_BASE_Q, st->time_base); + + av_log(s, AV_LOG_DEBUG, "offset=%"PRId64", reset_timestamps=%d, cur_entry.start_pts=%"PRId64", initial_offset=%"PRId64", pkt->pts=%"PRId64, + offset, seg->reset_timestamps, seg->cur_entry.start_pts, seg->initial_offset, pkt->pts); + if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; if (pkt->dts != AV_NOPTS_VALUE) @@ -1051,6 +1098,7 @@ static const AVOption options[] = { { "reset_timestamps", "reset timestamps at the beginning of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E }, { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E }, { "write_empty_segments", "allow writing empty 'filler' segments", OFFSET(write_empty), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E }, + { "segment_duration_ts", "set segment duration based on timebase", OFFSET(duration_ts), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, 86400000000LL, E}, { NULL }, }; diff --git a/libavutil/aes.c b/libavutil/aes.c index 397ea773898b1..88b94cc914fba 100644 --- a/libavutil/aes.c +++ b/libavutil/aes.c @@ -131,16 +131,26 @@ static inline void aes_crypt(AVAES *a, int s, const uint8_t *sbox, static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int rounds) { - while (count--) { - addkey_s(&a->state[1], src, &a->round_key[rounds]); - if (iv) - addkey_s(&a->state[1], iv, &a->state[1]); - aes_crypt(a, 2, sbox, enc_multbl); - addkey_d(dst, &a->state[0], &a->round_key[0]); - if (iv) - memcpy(iv, dst, 16); + int i = 0; + int pattern_block_length = a->crypt_byte_block + a->skip_byte_block; + + while (i < count) { + if (pattern_block_length == 0 || + i % pattern_block_length < a->crypt_byte_block) + { + addkey_s(&a->state[1], src, &a->round_key[rounds]); + if (iv) + addkey_s(&a->state[1], iv, &a->state[1]); + aes_crypt(a, 2, sbox, enc_multbl); + addkey_d(dst, &a->state[0], &a->round_key[0]); + if (iv) + memcpy(iv, dst, 16); + } else { + memcpy(dst, src, 16); // skip encryption + } src += 16; dst += 16; + i++; } } @@ -266,3 +276,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) return 0; } +void av_aes_set_pattern(struct AVAES *a, int crypt_byte_block, int skip_byte_block) { + a->crypt_byte_block = crypt_byte_block; + a->skip_byte_block = skip_byte_block; +} diff --git a/libavutil/aes.h b/libavutil/aes.h index 09efbda107397..e224bd86708ab 100644 --- a/libavutil/aes.h +++ b/libavutil/aes.h @@ -48,6 +48,11 @@ struct AVAES *av_aes_alloc(void); */ int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt); +/** + * Enable pattern encryption + */ +void av_aes_set_pattern(struct AVAES *a, int crypt_byte_block, int skip_byte_block); + /** * Encrypt or decrypt a buffer using a previously initialized context. * @param count number of 16 byte blocks diff --git a/libavutil/aes_internal.h b/libavutil/aes_internal.h index c9d6c24857df2..48535096d58c5 100644 --- a/libavutil/aes_internal.h +++ b/libavutil/aes_internal.h @@ -37,6 +37,8 @@ typedef struct AVAES { DECLARE_ALIGNED(16, av_aes_block, round_key)[15]; DECLARE_ALIGNED(16, av_aes_block, state)[2]; int rounds; + int crypt_byte_block; + int skip_byte_block; void (*crypt)(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int rounds); } AVAES; From cf9555c5c53356d50d819a21bd01c2a8096a0061 Mon Sep 17 00:00:00 2001 From: jan falkin Date: Thu, 5 Aug 2021 18:22:16 -0700 Subject: [PATCH 02/11] missed configure.debug --- configure.debug | 7556 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 7556 insertions(+) create mode 100755 configure.debug diff --git a/configure.debug b/configure.debug new file mode 100755 index 0000000000000..a9bfa1ca3f9f1 --- /dev/null +++ b/configure.debug @@ -0,0 +1,7556 @@ +#!/bin/sh +# +# FFmpeg configure script +# +# Copyright (c) 2000-2002 Fabrice Bellard +# Copyright (c) 2005-2008 Diego Biurrun +# Copyright (c) 2005-2008 Mans Rullgard +# + +# Prevent locale nonsense from breaking basic text processing. +LC_ALL=C +export LC_ALL + +# make sure we are running under a compatible shell +# try to make this part work with most shells + +try_exec(){ + echo "Trying shell $1" + type "$1" > /dev/null 2>&1 && exec "$@" +} + +unset foo +(: ${foo%%bar}) 2> /dev/null +E1="$?" + +(: ${foo?}) 2> /dev/null +E2="$?" + +if test "$E1" != 0 || test "$E2" = 0; then + echo "Broken shell detected. Trying alternatives." + export FF_CONF_EXEC + if test "0$FF_CONF_EXEC" -lt 1; then + FF_CONF_EXEC=1 + try_exec bash "$0" "$@" + fi + if test "0$FF_CONF_EXEC" -lt 2; then + FF_CONF_EXEC=2 + try_exec ksh "$0" "$@" + fi + if test "0$FF_CONF_EXEC" -lt 3; then + FF_CONF_EXEC=3 + try_exec /usr/xpg4/bin/sh "$0" "$@" + fi + echo "No compatible shell script interpreter found." + echo "This configure script requires a POSIX-compatible shell" + echo "such as bash or ksh." + echo "THIS IS NOT A BUG IN FFMPEG, DO NOT REPORT IT AS SUCH." + echo "Instead, install a working POSIX-compatible shell." + echo "Disabling this configure test will create a broken FFmpeg." + if test "$BASH_VERSION" = '2.04.0(1)-release'; then + echo "This bash version ($BASH_VERSION) is broken on your platform." + echo "Upgrade to a later version if available." + fi + exit 1 +fi + +test -d /usr/xpg4/bin && PATH=/usr/xpg4/bin:$PATH + +show_help(){ + cat </dev/null 2>&1; then + ncolors=$(tput colors) + if test -n "$ncolors" && test $ncolors -ge 8; then + bold_color=$(tput bold) + warn_color=$(tput setaf 3) + error_color=$(tput setaf 1) + reset_color=$(tput sgr0) + fi + # 72 used instead of 80 since that's the default of pr + ncols=$(tput cols) +fi +: ${ncols:=72} + +log(){ + echo "$@" >> $logfile +} + +log_file(){ + log BEGIN "$1" + log_file_i=1 + while IFS= read -r log_file_line; do + printf '%5d\t%s\n' "$log_file_i" "$log_file_line" + log_file_i=$(($log_file_i+1)) + done < "$1" >> "$logfile" + log END "$1" +} + +warn(){ + log "WARNING: $*" + WARNINGS="${WARNINGS}WARNING: $*\n" +} + +die(){ + log "$@" + echo "$error_color$bold_color$@$reset_color" + cat <>file; + } else if (file ~ /\\.asm\$/) { + printf(\"%%define %s %d\\n\", c, v) >>file; + } else if (file ~ /\\.mak\$/) { + n = -v ? \"\" : \"!\"; + printf(\"%s%s=yes\\n\", n, c) >>file; + } else if (file ~ /\\.texi\$/) { + pre = -v ? \"\" : \"@c \"; + yesno = \$2; + c2 = tolower(c); + gsub(/_/, \"-\", c2); + printf(\"%s@set %s %s\\n\", pre, c2, yesno) >>file; + } + } + }" +} + +print_enabled(){ + suf=$1 + shift + for v; do + enabled $v && printf "%s\n" ${v%$suf} + done +} + +append(){ + var=$1 + shift + eval "$var=\"\$$var $*\"" +} + +prepend(){ + var=$1 + shift + eval "$var=\"$* \$$var\"" +} + +reverse () { + eval ' + reverse_out= + for v in $'$1'; do + reverse_out="$v $reverse_out" + done + '$1'=$reverse_out + ' +} + +# keeps the last occurence of each non-unique item +unique(){ + unique_out= + eval unique_in=\$$1 + reverse unique_in + for v in $unique_in; do + # " $unique_out" +space such that every item is surrounded with spaces + case " $unique_out" in *" $v "*) continue; esac # already in list + unique_out="$unique_out$v " + done + reverse unique_out + eval $1=\$unique_out +} + +resolve(){ + resolve_out= + eval resolve_in=\$$1 + for v in $resolve_in; do + eval 'resolve_out="$resolve_out$'$v' "' + done + eval $1=\$resolve_out +} + +add_cppflags(){ + append CPPFLAGS "$@" +} + +add_cflags(){ + append CFLAGS $($cflags_filter "$@") +} + +add_cflags_headers(){ + append CFLAGS_HEADERS $($cflags_filter "$@") +} + +add_cxxflags(){ + append CXXFLAGS $($cflags_filter "$@") +} + +add_objcflags(){ + append OBJCFLAGS $($objcflags_filter "$@") +} + +add_asflags(){ + append ASFLAGS $($asflags_filter "$@") +} + +add_ldflags(){ + append LDFLAGS $($ldflags_filter "$@") +} + +add_ldexeflags(){ + append LDEXEFLAGS $($ldflags_filter "$@") +} + +add_ldsoflags(){ + append LDSOFLAGS $($ldflags_filter "$@") +} + +add_extralibs(){ + prepend extralibs $($ldflags_filter "$@") +} + +add_stripflags(){ + append ASMSTRIPFLAGS "$@" +} + +add_host_cppflags(){ + append host_cppflags "$@" +} + +add_host_cflags(){ + append host_cflags $($host_cflags_filter "$@") +} + +add_host_ldflags(){ + append host_ldflags $($host_ldflags_filter "$@") +} + +add_compat(){ + append compat_objs $1 + shift + map 'add_cppflags -D$v' "$@" +} + +test_cmd(){ + log "$@" + "$@" >> $logfile 2>&1 +} + +test_stat(){ + log test_stat "$@" + stat "$1" >> $logfile 2>&1 +} + +cc_e(){ + eval printf '%s\\n' $CC_E +} + +cc_o(){ + eval printf '%s\\n' $CC_O +} + +as_o(){ + eval printf '%s\\n' $AS_O +} + +x86asm_o(){ + eval printf '%s\\n' $X86ASM_O +} + +ld_o(){ + eval printf '%s\\n' $LD_O +} + +hostcc_e(){ + eval printf '%s\\n' $HOSTCC_E +} + +hostcc_o(){ + eval printf '%s\\n' $HOSTCC_O +} + +nvcc_o(){ + eval printf '%s\\n' $NVCC_O +} + +test_cc(){ + log test_cc "$@" + cat > $TMPC + log_file $TMPC + test_cmd $cc $CPPFLAGS $CFLAGS "$@" $CC_C $(cc_o $TMPO) $TMPC +} + +test_cxx(){ + log test_cxx "$@" + cat > $TMPCPP + log_file $TMPCPP + test_cmd $cxx $CPPFLAGS $CFLAGS $CXXFLAGS "$@" $CXX_C -o $TMPO $TMPCPP +} + +test_objcc(){ + log test_objcc "$@" + cat > $TMPM + log_file $TMPM + test_cmd $objcc -Werror=missing-prototypes $CPPFLAGS $CFLAGS $OBJCFLAGS "$@" $OBJCC_C $(cc_o $TMPO) $TMPM +} + +test_nvcc(){ + log test_nvcc "$@" + cat > $TMPCU + log_file $TMPCU + tmpcu_=$TMPCU + tmpo_=$TMPO + [ -x "$(command -v cygpath)" ] && tmpcu_=$(cygpath -m $tmpcu_) && tmpo_=$(cygpath -m $tmpo_) + test_cmd $nvcc $nvccflags "$@" $NVCC_C $(nvcc_o $tmpo_) $tmpcu_ +} + +check_nvcc() { + log check_nvcc "$@" + name=$1 + shift 1 + disabled $name && return + disable $name + test_nvcc "$@" < $TMPC + log_file $TMPC + test_cmd $cc $CPPFLAGS $CFLAGS "$@" $(cc_e $TMPO) $TMPC +} + +test_as(){ + log test_as "$@" + cat > $TMPS + log_file $TMPS + test_cmd $as $CPPFLAGS $ASFLAGS "$@" $AS_C $(as_o $TMPO) $TMPS +} + +test_x86asm(){ + log test_x86asm "$@" + echo "$1" > $TMPASM + log_file $TMPASM + shift + test_cmd $x86asmexe $X86ASMFLAGS -Werror "$@" $(x86asm_o $TMPO) $TMPASM +} + +check_cmd(){ + log check_cmd "$@" + cmd=$1 + disabled $cmd && return + disable $cmd + test_cmd $@ && enable $cmd +} + +check_as(){ + log check_as "$@" + name=$1 + code=$2 + shift 2 + disable $name + test_as $@ < $TMPC <" +} + +test_code(){ + log test_code "$@" + check=$1 + headers=$2 + code=$3 + shift 3 + { + for hdr in $headers; do + print_include $hdr + done + echo "int main(void) { $code; return 0; }" + } | test_$check "$@" +} + +check_cppflags(){ + log check_cppflags "$@" + test_cpp "$@" < +EOF +} + +test_cflags(){ + log test_cflags "$@" + set -- $($cflags_filter "$@") + test_cc "$@" <" + echo "int main(void) { return 0; }" + } | test_objcc && test_stat "$TMPO" && enable_sanitized $header +} + +check_apple_framework(){ + log check_apple_framework "$@" + framework="$1" + name="$(tolower $framework)" + header="${framework}/${framework}.h" + disable $name + check_header_objcc $header && + enable $name && eval ${name}_extralibs='"-framework $framework"' +} + +check_func(){ + log check_func "$@" + func=$1 + shift + disable $func + test_ld "cc" "$@" < +#include +float foo(complex float f, complex float g) { return $func($args); } +int main(void){ return (int) foo; } +EOF +} + +check_mathfunc(){ + log check_mathfunc "$@" + func=$1 + narg=$2 + shift 2 + test $narg = 2 && args="f, g" || args="f" + disable $func + test_ld "cc" "$@" < +float foo(float f, float g) { return $func($args); } +int main(void){ return (int) foo; } +EOF +} + +check_func_headers(){ + log check_func_headers "$@" + headers=$1 + funcs=$2 + shift 2 + { + for hdr in $headers; do + print_include $hdr + done + echo "#include " + for func in $funcs; do + echo "long check_$func(void) { return (long) $func; }" + done + echo "int main(void) { int ret = 0;" + # LTO could optimize out the test functions without this + for func in $funcs; do + echo " ret |= ((intptr_t)check_$func) & 0xFFFF;" + done + echo "return ret; }" + } | test_ld "cc" "$@" && enable $funcs && enable_sanitized $headers +} + +check_class_headers_cpp(){ + log check_class_headers_cpp "$@" + headers=$1 + classes=$2 + shift 2 + { + for hdr in $headers; do + echo "#include <$hdr>" + done + echo "int main(void) { " + i=1 + for class in $classes; do + echo "$class obj$i;" + i=$(expr $i + 1) + done + echo "return 0; }" + } | test_ld "cxx" "$@" && enable $funcs && enable_sanitized $headers +} + +test_cpp_condition(){ + log test_cpp_condition "$@" + header=$1 + condition=$2 + shift 2 + test_cpp "$@" < +#if !($condition) +#error "unsatisfied condition: $condition" +#endif +EOF +} + +check_cpp_condition(){ + log check_cpp_condition "$@" + name=$1 + shift 1 + disable $name + test_cpp_condition "$@" && enable $name +} + +test_cflags_cc(){ + log test_cflags_cc "$@" + flags=$1 + header=$2 + condition=$3 + shift 3 + set -- $($cflags_filter "$flags") + test_cc "$@" < +#if !($condition) +#error "unsatisfied condition: $condition" +#endif +EOF +} + +check_lib(){ + log check_lib "$@" + name="$1" + headers="$2" + funcs="$3" + shift 3 + disable $name + check_func_headers "$headers" "$funcs" "$@" && + enable $name && eval ${name}_extralibs="\$@" +} + +check_lib_cpp(){ + log check_lib_cpp "$@" + name="$1" + headers="$2" + classes="$3" + shift 3 + disable $name + check_class_headers_cpp "$headers" "$classes" "$@" && + enable $name && eval ${name}_extralibs="\$@" +} + +test_pkg_config(){ + log test_pkg_config "$@" + name="$1" + pkg_version="$2" + pkg="${2%% *}" + headers="$3" + funcs="$4" + shift 4 + disable $name + test_cmd $pkg_config --exists --print-errors $pkg_version || return + pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) + pkg_libs=$($pkg_config --libs $pkg_config_flags $pkg) + check_func_headers "$headers" "$funcs" $pkg_cflags $pkg_libs "$@" && + enable $name && + set_sanitized "${name}_cflags" $pkg_cflags && + set_sanitized "${name}_extralibs" $pkg_libs +} + +check_pkg_config(){ + log check_pkg_config "$@" + name="$1" + test_pkg_config "$@" && + eval add_cflags \$${name}_cflags +} + +test_exec(){ + test_ld "cc" "$@" && { enabled cross_compile || $TMPE >> $logfile 2>&1; } +} + +check_exec_crash(){ + log check_exec_crash "$@" + code=$(cat) + + # exit() is not async signal safe. _Exit (C99) and _exit (POSIX) + # are safe but may not be available everywhere. Thus we use + # raise(SIGTERM) instead. The check is run in a subshell so we + # can redirect the "Terminated" message from the shell. SIGBUS + # is not defined by standard C so it is used conditionally. + + (test_exec "$@") >> $logfile 2>&1 < +static void sighandler(int sig){ + raise(SIGTERM); +} +int foo(void){ + $code +} +int (*func_ptr)(void) = foo; +int main(void){ + signal(SIGILL, sighandler); + signal(SIGFPE, sighandler); + signal(SIGSEGV, sighandler); +#ifdef SIGBUS + signal(SIGBUS, sighandler); +#endif + return func_ptr(); +} +EOF +} + +check_type(){ + log check_type "$@" + headers=$1 + type=$2 + shift 2 + disable_sanitized "$type" + test_code cc "$headers" "$type v" "$@" && enable_sanitized "$type" +} + +check_struct(){ + log check_struct "$@" + headers=$1 + struct=$2 + member=$3 + shift 3 + disable_sanitized "${struct}_${member}" + test_code cc "$headers" "const void *p = &(($struct *)0)->$member" "$@" && + enable_sanitized "${struct}_${member}" +} + +check_builtin(){ + log check_builtin "$@" + name=$1 + headers=$2 + builtin=$3 + shift 3 + disable "$name" + test_code ld "$headers" "$builtin" "cc" "$@" && enable "$name" +} + +check_compile_assert(){ + log check_compile_assert "$@" + name=$1 + headers=$2 + condition=$3 + shift 3 + disable "$name" + test_code cc "$headers" "char c[2 * !!($condition) - 1]" "$@" && enable "$name" +} + +check_cc(){ + log check_cc "$@" + name=$1 + shift + disable "$name" + test_code cc "$@" && enable "$name" +} + +require(){ + log require "$@" + name_version="$1" + name="${1%% *}" + shift + check_lib $name "$@" || die "ERROR: $name_version not found" +} + +require_cc(){ + log require_cc "$@" + name="$1" + check_cc "$@" || die "ERROR: $name failed" +} + +require_cpp(){ + name="$1" + headers="$2" + classes="$3" + shift 3 + check_lib_cpp "$headers" "$classes" "$@" || die "ERROR: $name not found" +} + +require_headers(){ + log require_headers "$@" + headers="$1" + check_headers "$@" || die "ERROR: $headers not found" +} + +require_cpp_condition(){ + log require_cpp_condition "$@" + condition="$3" + check_cpp_condition "$@" || die "ERROR: $condition not satisfied" +} + +require_pkg_config(){ + log require_pkg_config "$@" + pkg_version="$2" + check_pkg_config "$@" || die "ERROR: $pkg_version not found using pkg-config$pkg_config_fail_message" +} + +test_host_cc(){ + log test_host_cc "$@" + cat > $TMPC + log_file $TMPC + test_cmd $host_cc $host_cflags "$@" $HOSTCC_C $(hostcc_o $TMPO) $TMPC +} + +test_host_cpp(){ + log test_host_cpp "$@" + cat > $TMPC + log_file $TMPC + test_cmd $host_cc $host_cppflags $host_cflags "$@" $(hostcc_e $TMPO) $TMPC +} + +check_host_cppflags(){ + log check_host_cppflags "$@" + test_host_cpp "$@" < +EOF +} + +check_host_cflags(){ + log check_host_cflags "$@" + set -- $($host_cflags_filter "$@") + test_host_cc "$@" < +#if !($condition) +#error "unsatisfied condition: $condition" +#endif +EOF +} + +check_host_cpp_condition(){ + log check_host_cpp_condition "$@" + name=$1 + shift 1 + disable $name + test_host_cpp_condition "$@" && enable $name +} + +cp_if_changed(){ + cmp -s "$1" "$2" && { test "$quiet" != "yes" && echo "$2 is unchanged"; } && return + mkdir -p "$(dirname $2)" + cp -f "$1" "$2" +} + +# CONFIG_LIST contains configurable options, while HAVE_LIST is for +# system-dependent things. + +AVCODEC_COMPONENTS=" + bsfs + decoders + encoders + hwaccels + parsers +" + +AVDEVICE_COMPONENTS=" + indevs + outdevs +" + +AVFILTER_COMPONENTS=" + filters +" + +AVFORMAT_COMPONENTS=" + demuxers + muxers + protocols +" + +COMPONENT_LIST=" + $AVCODEC_COMPONENTS + $AVDEVICE_COMPONENTS + $AVFILTER_COMPONENTS + $AVFORMAT_COMPONENTS +" + +EXAMPLE_LIST=" + avio_dir_cmd_example + avio_reading_example + decode_audio_example + decode_video_example + demuxing_decoding_example + encode_audio_example + encode_video_example + extract_mvs_example + filter_audio_example + filtering_audio_example + filtering_video_example + http_multiclient_example + hw_decode_example + metadata_example + muxing_example + qsvdec_example + remuxing_example + resampling_audio_example + scaling_video_example + transcode_aac_example + transcoding_example + vaapi_encode_example + vaapi_transcode_example +" + +EXTERNAL_AUTODETECT_LIBRARY_LIST=" + alsa + appkit + avfoundation + bzlib + coreimage + iconv + libxcb + libxcb_shm + libxcb_shape + libxcb_xfixes + lzma + schannel + sdl2 + securetransport + sndio + xlib + zlib +" + +EXTERNAL_LIBRARY_GPL_LIST=" + avisynth + frei0r + libcdio + libdavs2 + librubberband + libvidstab + libx264 + libx265 + libxavs + libxavs2 + libxvid +" + +EXTERNAL_LIBRARY_NONFREE_LIST=" + decklink + libfdk_aac + openssl + libtls +" + +EXTERNAL_LIBRARY_VERSION3_LIST=" + gmp + libaribb24 + liblensfun + libopencore_amrnb + libopencore_amrwb + libvmaf + libvo_amrwbenc + mbedtls + rkmpp +" + +EXTERNAL_LIBRARY_GPLV3_LIST=" + libsmbclient +" + +EXTERNAL_LIBRARY_LIST=" + $EXTERNAL_LIBRARY_GPL_LIST + $EXTERNAL_LIBRARY_NONFREE_LIST + $EXTERNAL_LIBRARY_VERSION3_LIST + $EXTERNAL_LIBRARY_GPLV3_LIST + chromaprint + gcrypt + gnutls + jni + ladspa + libaom + libass + libbluray + libbs2b + libcaca + libcelt + libcodec2 + libdav1d + libdc1394 + libdrm + libflite + libfontconfig + libfreetype + libfribidi + libgme + libgsm + libiec61883 + libilbc + libjack + libklvanc + libkvazaar + libmodplug + libmp3lame + libmysofa + libopencv + libopenh264 + libopenjpeg + libopenmpt + libopus + libpulse + librsvg + librtmp + libshine + libsmbclient + libsnappy + libsoxr + libspeex + libsrt + libssh + libtensorflow + libtesseract + libtheora + libtwolame + libv4l2 + libvorbis + libvpx + libwavpack + libwebp + libxml2 + libzimg + libzmq + libzvbi + lv2 + mediacodec + openal + opengl + pocketsphinx + vapoursynth +" + +HWACCEL_AUTODETECT_LIBRARY_LIST=" + amf + audiotoolbox + crystalhd + cuda + cuda_llvm + cuvid + d3d11va + dxva2 + ffnvcodec + nvdec + nvenc + vaapi + vdpau + videotoolbox + v4l2_m2m + xvmc +" + +# catchall list of things that require external libs to link +EXTRALIBS_LIST=" + cpu_init + cws2fws +" + +HWACCEL_LIBRARY_NONFREE_LIST=" + cuda_nvcc + cuda_sdk + libnpp +" + +HWACCEL_LIBRARY_LIST=" + $HWACCEL_LIBRARY_NONFREE_LIST + libmfx + mmal + omx + opencl +" + +DOCUMENT_LIST=" + doc + htmlpages + manpages + podpages + txtpages +" + +FEATURE_LIST=" + ftrapv + gray + hardcoded_tables + omx_rpi + runtime_cpudetect + safe_bitstream_reader + shared + small + static + swscale_alpha +" + +# this list should be kept in linking order +LIBRARY_LIST=" + avdevice + avfilter + swscale + postproc + avformat + avcodec + swresample + avresample + avutil +" + +LICENSE_LIST=" + gpl + nonfree + version3 +" + +PROGRAM_LIST=" + ffplay + ffprobe + ffmpeg +" + +SUBSYSTEM_LIST=" + dct + dwt + error_resilience + faan + fast_unaligned + fft + lsp + lzo + mdct + pixelutils + network + rdft +" + +# COMPONENT_LIST needs to come last to ensure correct dependency checking +CONFIG_LIST=" + $DOCUMENT_LIST + $EXAMPLE_LIST + $EXTERNAL_LIBRARY_LIST + $EXTERNAL_AUTODETECT_LIBRARY_LIST + $HWACCEL_LIBRARY_LIST + $HWACCEL_AUTODETECT_LIBRARY_LIST + $FEATURE_LIST + $LICENSE_LIST + $LIBRARY_LIST + $PROGRAM_LIST + $SUBSYSTEM_LIST + autodetect + fontconfig + linux_perf + memory_poisoning + neon_clobber_test + ossfuzz + pic + thumb + valgrind_backtrace + xmm_clobber_test + $COMPONENT_LIST +" + +THREADS_LIST=" + pthreads + os2threads + w32threads +" + +ATOMICS_LIST=" + atomics_gcc + atomics_suncc + atomics_win32 +" + +AUTODETECT_LIBS=" + $EXTERNAL_AUTODETECT_LIBRARY_LIST + $HWACCEL_AUTODETECT_LIBRARY_LIST + $THREADS_LIST +" + +ARCH_LIST=" + aarch64 + alpha + arm + avr32 + avr32_ap + avr32_uc + bfin + ia64 + m68k + mips + mips64 + parisc + ppc + ppc64 + s390 + sh4 + sparc + sparc64 + tilegx + tilepro + tomi + x86 + x86_32 + x86_64 +" + +ARCH_EXT_LIST_ARM=" + armv5te + armv6 + armv6t2 + armv8 + neon + vfp + vfpv3 + setend +" + +ARCH_EXT_LIST_MIPS=" + mipsfpu + mips32r2 + mips32r5 + mips64r2 + mips32r6 + mips64r6 + mipsdsp + mipsdspr2 + msa + msa2 +" + +ARCH_EXT_LIST_LOONGSON=" + loongson2 + loongson3 + mmi +" + +ARCH_EXT_LIST_X86_SIMD=" + aesni + amd3dnow + amd3dnowext + avx + avx2 + avx512 + fma3 + fma4 + mmx + mmxext + sse + sse2 + sse3 + sse4 + sse42 + ssse3 + xop +" + +ARCH_EXT_LIST_PPC=" + altivec + dcbzl + ldbrx + power8 + ppc4xx + vsx +" + +ARCH_EXT_LIST_X86=" + $ARCH_EXT_LIST_X86_SIMD + cpunop + i686 +" + +ARCH_EXT_LIST=" + $ARCH_EXT_LIST_ARM + $ARCH_EXT_LIST_PPC + $ARCH_EXT_LIST_X86 + $ARCH_EXT_LIST_MIPS + $ARCH_EXT_LIST_LOONGSON +" + +ARCH_FEATURES=" + aligned_stack + fast_64bit + fast_clz + fast_cmov + local_aligned + simd_align_16 + simd_align_32 + simd_align_64 +" + +BUILTIN_LIST=" + atomic_cas_ptr + machine_rw_barrier + MemoryBarrier + mm_empty + rdtsc + sem_timedwait + sync_val_compare_and_swap +" +HAVE_LIST_CMDLINE=" + inline_asm + symver + x86asm +" + +HAVE_LIST_PUB=" + bigendian + fast_unaligned +" + +HEADERS_LIST=" + arpa_inet_h + asm_types_h + cdio_paranoia_h + cdio_paranoia_paranoia_h + cuda_h + dispatch_dispatch_h + dev_bktr_ioctl_bt848_h + dev_bktr_ioctl_meteor_h + dev_ic_bt8xx_h + dev_video_bktr_ioctl_bt848_h + dev_video_meteor_ioctl_meteor_h + direct_h + dirent_h + dxgidebug_h + dxva_h + ES2_gl_h + gsm_h + io_h + linux_perf_event_h + machine_ioctl_bt848_h + machine_ioctl_meteor_h + malloc_h + opencv2_core_core_c_h + OpenGL_gl3_h + poll_h + sys_param_h + sys_resource_h + sys_select_h + sys_soundcard_h + sys_time_h + sys_un_h + sys_videoio_h + termios_h + udplite_h + unistd_h + valgrind_valgrind_h + windows_h + winsock2_h +" + +INTRINSICS_LIST=" + intrinsics_neon +" + +COMPLEX_FUNCS=" + cabs + cexp +" + +MATH_FUNCS=" + atanf + atan2f + cbrt + cbrtf + copysign + cosf + erf + exp2 + exp2f + expf + hypot + isfinite + isinf + isnan + ldexpf + llrint + llrintf + log2 + log2f + log10f + lrint + lrintf + powf + rint + round + roundf + sinf + trunc + truncf +" + +SYSTEM_FEATURES=" + dos_paths + libc_msvcrt + MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS + section_data_rel_ro + threads + uwp + winrt +" + +SYSTEM_FUNCS=" + access + aligned_malloc + arc4random + clock_gettime + closesocket + CommandLineToArgvW + fcntl + getaddrinfo + gethrtime + getopt + GetProcessAffinityMask + GetProcessMemoryInfo + GetProcessTimes + getrusage + GetSystemTimeAsFileTime + gettimeofday + glob + glXGetProcAddress + gmtime_r + inet_aton + isatty + kbhit + localtime_r + lstat + lzo1x_999_compress + mach_absolute_time + MapViewOfFile + memalign + mkstemp + mmap + mprotect + nanosleep + PeekNamedPipe + posix_memalign + pthread_cancel + sched_getaffinity + SecItemImport + SetConsoleTextAttribute + SetConsoleCtrlHandler + setmode + setrlimit + Sleep + strerror_r + sysconf + sysctl + usleep + UTGetOSTypeFromString + VirtualAlloc + wglGetProcAddress +" + +SYSTEM_LIBRARIES=" + bcrypt + vaapi_drm + vaapi_x11 + vdpau_x11 +" + +TOOLCHAIN_FEATURES=" + as_arch_directive + as_dn_directive + as_fpu_directive + as_func + as_object_arch + asm_mod_q + blocks_extension + ebp_available + ebx_available + gnu_as + gnu_windres + ibm_asm + inline_asm_direct_symbol_refs + inline_asm_labels + inline_asm_nonlocal_labels + pragma_deprecated + rsync_contimeout + symver_asm_label + symver_gnu_asm + vfp_args + xform_asm + xmm_clobbers +" + +TYPES_LIST=" + kCMVideoCodecType_HEVC + kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange + kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ + kCVImageBufferTransferFunction_ITU_R_2100_HLG + kCVImageBufferTransferFunction_Linear + socklen_t + struct_addrinfo + struct_group_source_req + struct_ip_mreq_source + struct_ipv6_mreq + struct_msghdr_msg_flags + struct_pollfd + struct_rusage_ru_maxrss + struct_sctp_event_subscribe + struct_sockaddr_in6 + struct_sockaddr_sa_len + struct_sockaddr_storage + struct_stat_st_mtim_tv_nsec + struct_v4l2_frmivalenum_discrete +" + +HAVE_LIST=" + $ARCH_EXT_LIST + $(add_suffix _external $ARCH_EXT_LIST) + $(add_suffix _inline $ARCH_EXT_LIST) + $ARCH_FEATURES + $BUILTIN_LIST + $COMPLEX_FUNCS + $HAVE_LIST_CMDLINE + $HAVE_LIST_PUB + $HEADERS_LIST + $INTRINSICS_LIST + $MATH_FUNCS + $SYSTEM_FEATURES + $SYSTEM_FUNCS + $SYSTEM_LIBRARIES + $THREADS_LIST + $TOOLCHAIN_FEATURES + $TYPES_LIST + makeinfo + makeinfo_html + opencl_d3d11 + opencl_drm_arm + opencl_drm_beignet + opencl_dxva2 + opencl_vaapi_beignet + opencl_vaapi_intel_media + perl + pod2man + texi2html +" + +# options emitted with CONFIG_ prefix but not available on the command line +CONFIG_EXTRA=" + aandcttables + ac3dsp + adts_header + audio_frame_queue + audiodsp + blockdsp + bswapdsp + cabac + cbs + cbs_av1 + cbs_h264 + cbs_h265 + cbs_jpeg + cbs_mpeg2 + cbs_vp9 + dirac_parse + dnn + dvprofile + exif + faandct + faanidct + fdctdsp + flacdsp + fmtconvert + frame_thread_encoder + g722dsp + golomb + gplv3 + h263dsp + h264chroma + h264dsp + h264parse + h264pred + h264qpel + hevcparse + hpeldsp + huffman + huffyuvdsp + huffyuvencdsp + idctdsp + iirfilter + mdct15 + intrax8 + iso_media + ividsp + jpegtables + lgplv3 + libx262 + llauddsp + llviddsp + llvidencdsp + lpc + lzf + me_cmp + mpeg_er + mpegaudio + mpegaudiodsp + mpegaudioheader + mpegvideo + mpegvideoenc + mss34dsp + pixblockdsp + qpeldsp + qsv + qsvdec + qsvenc + qsvvpp + rangecoder + riffdec + riffenc + rtpdec + rtpenc_chain + rv34dsp + scene_sad + sinewin + snappy + srtp + startcode + texturedsp + texturedspenc + tpeldsp + vaapi_1 + vaapi_encode + vc1dsp + videodsp + vp3dsp + vp56dsp + vp8dsp + wma_freqs + wmv2dsp +" + +CMDLINE_SELECT=" + $ARCH_EXT_LIST + $CONFIG_LIST + $HAVE_LIST_CMDLINE + $THREADS_LIST + asm + cross_compile + debug + extra_warnings + logging + lto + optimizations + rpath + stripping +" + +PATHS_LIST=" + bindir + datadir + docdir + incdir + libdir + mandir + pkgconfigdir + prefix + shlibdir + install_name_dir +" + +CMDLINE_SET=" + $PATHS_LIST + ar + arch + as + assert_level + build_suffix + cc + objcc + cpu + cross_prefix + custom_allocator + cxx + dep_cc + doxygen + env + extra_version + gas + host_cc + host_cflags + host_extralibs + host_ld + host_ldflags + host_os + ignore_tests + install + ld + ln_s + logfile + malloc_prefix + nm + optflags + nvcc + nvccflags + pkg_config + pkg_config_flags + progs_suffix + random_seed + ranlib + samples + strip + sws_max_filter_size + sysinclude + sysroot + target_exec + target_os + target_path + target_samples + tempprefix + toolchain + valgrind + windres + x86asmexe +" + +CMDLINE_APPEND=" + extra_cflags + extra_cxxflags + extra_objcflags + host_cppflags +" + +# code dependency declarations + +# architecture extensions + +armv5te_deps="arm" +armv6_deps="arm" +armv6t2_deps="arm" +armv8_deps="aarch64" +neon_deps_any="aarch64 arm" +intrinsics_neon_deps="neon" +vfp_deps_any="aarch64 arm" +vfpv3_deps="vfp" +setend_deps="arm" + +map 'eval ${v}_inline_deps=inline_asm' $ARCH_EXT_LIST_ARM + +altivec_deps="ppc" +dcbzl_deps="ppc" +ldbrx_deps="ppc" +ppc4xx_deps="ppc" +vsx_deps="altivec" +power8_deps="vsx" + +loongson2_deps="mips" +loongson3_deps="mips" +mips32r2_deps="mips" +mips32r5_deps="mips" +mips32r6_deps="mips" +mips64r2_deps="mips" +mips64r6_deps="mips" +mipsfpu_deps="mips" +mipsdsp_deps="mips" +mipsdspr2_deps="mips" +mmi_deps="mips" +msa_deps="mipsfpu" +msa2_deps="msa" + +cpunop_deps="i686" +x86_64_select="i686" +x86_64_suggest="fast_cmov" + +amd3dnow_deps="mmx" +amd3dnowext_deps="amd3dnow" +i686_deps="x86" +mmx_deps="x86" +mmxext_deps="mmx" +sse_deps="mmxext" +sse2_deps="sse" +sse3_deps="sse2" +ssse3_deps="sse3" +sse4_deps="ssse3" +sse42_deps="sse4" +aesni_deps="sse42" +avx_deps="sse42" +xop_deps="avx" +fma3_deps="avx" +fma4_deps="avx" +avx2_deps="avx" +avx512_deps="avx2" + +mmx_external_deps="x86asm" +mmx_inline_deps="inline_asm x86" +mmx_suggest="mmx_external mmx_inline" + +for ext in $(filter_out mmx $ARCH_EXT_LIST_X86_SIMD); do + eval dep=\$${ext}_deps + eval ${ext}_external_deps='"${dep}_external"' + eval ${ext}_inline_deps='"${dep}_inline"' + eval ${ext}_suggest='"${ext}_external ${ext}_inline"' +done + +aligned_stack_if_any="aarch64 ppc x86" +fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 sparc64 x86_64" +fast_clz_if_any="aarch64 alpha avr32 mips ppc x86" +fast_unaligned_if_any="aarch64 ppc x86" +simd_align_16_if_any="altivec neon sse" +simd_align_32_if_any="avx" +simd_align_64_if_any="avx512" + +# system capabilities +linux_perf_deps="linux_perf_event_h" +symver_if_any="symver_asm_label symver_gnu_asm" +valgrind_backtrace_conflict="optimizations" +valgrind_backtrace_deps="valgrind_valgrind_h" + +# threading support +atomics_gcc_if="sync_val_compare_and_swap" +atomics_suncc_if="atomic_cas_ptr machine_rw_barrier" +atomics_win32_if="MemoryBarrier" +atomics_native_if_any="$ATOMICS_LIST" +w32threads_deps="atomics_native" +threads_if_any="$THREADS_LIST" + +# subsystems +cbs_av1_select="cbs" +cbs_h264_select="cbs" +cbs_h265_select="cbs" +cbs_jpeg_select="cbs" +cbs_mpeg2_select="cbs" +cbs_vp9_select="cbs" +dct_select="rdft" +dirac_parse_select="golomb" +dnn_suggest="libtensorflow" +error_resilience_select="me_cmp" +faandct_deps="faan" +faandct_select="fdctdsp" +faanidct_deps="faan" +faanidct_select="idctdsp" +h264dsp_select="startcode" +hevcparse_select="golomb" +frame_thread_encoder_deps="encoders threads" +intrax8_select="blockdsp idctdsp" +mdct_select="fft" +mdct15_select="fft" +me_cmp_select="fdctdsp idctdsp pixblockdsp" +mpeg_er_select="error_resilience" +mpegaudio_select="mpegaudiodsp mpegaudioheader" +mpegaudiodsp_select="dct" +mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp mpeg_er videodsp" +mpegvideoenc_select="aandcttables me_cmp mpegvideo pixblockdsp qpeldsp" +vc1dsp_select="h264chroma qpeldsp startcode" +rdft_select="fft" + +# decoders / encoders +aac_decoder_select="adts_header mdct15 mdct sinewin" +aac_fixed_decoder_select="adts_header mdct sinewin" +aac_encoder_select="audio_frame_queue iirfilter lpc mdct sinewin" +aac_latm_decoder_select="aac_decoder aac_latm_parser" +ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" +ac3_fixed_decoder_select="ac3_parser ac3dsp bswapdsp mdct" +ac3_encoder_select="ac3dsp audiodsp mdct me_cmp" +ac3_fixed_encoder_select="ac3dsp audiodsp mdct me_cmp" +adpcm_g722_decoder_select="g722dsp" +adpcm_g722_encoder_select="g722dsp" +aic_decoder_select="golomb idctdsp" +alac_encoder_select="lpc" +als_decoder_select="bswapdsp" +amrnb_decoder_select="lsp" +amrwb_decoder_select="lsp" +amv_decoder_select="sp5x_decoder exif" +amv_encoder_select="jpegtables mpegvideoenc" +ape_decoder_select="bswapdsp llauddsp" +apng_decoder_deps="zlib" +apng_encoder_deps="zlib" +apng_encoder_select="llvidencdsp" +aptx_decoder_select="audio_frame_queue" +aptx_encoder_select="audio_frame_queue" +aptx_hd_decoder_select="audio_frame_queue" +aptx_hd_encoder_select="audio_frame_queue" +asv1_decoder_select="blockdsp bswapdsp idctdsp" +asv1_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" +asv2_decoder_select="blockdsp bswapdsp idctdsp" +asv2_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" +atrac1_decoder_select="mdct sinewin" +atrac3_decoder_select="mdct" +atrac3p_decoder_select="mdct sinewin" +atrac9_decoder_select="mdct" +avrn_decoder_select="exif jpegtables" +bink_decoder_select="blockdsp hpeldsp" +binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs" +binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs" +cavs_decoder_select="blockdsp golomb h264chroma idctdsp qpeldsp videodsp" +clearvideo_decoder_select="idctdsp" +cllc_decoder_select="bswapdsp" +comfortnoise_encoder_select="lpc" +cook_decoder_select="audiodsp mdct sinewin" +cscd_decoder_select="lzo" +cscd_decoder_suggest="zlib" +dca_decoder_select="mdct" +dds_decoder_select="texturedsp" +dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc" +dnxhd_decoder_select="blockdsp idctdsp" +dnxhd_encoder_select="blockdsp fdctdsp idctdsp mpegvideoenc pixblockdsp" +dolby_e_decoder_select="mdct" +dvvideo_decoder_select="dvprofile idctdsp" +dvvideo_encoder_select="dvprofile fdctdsp me_cmp pixblockdsp" +dxa_decoder_deps="zlib" +dxv_decoder_select="lzf texturedsp" +eac3_decoder_select="ac3_decoder" +eac3_encoder_select="ac3_encoder" +eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo" +eatgq_decoder_select="aandcttables" +eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp" +exr_decoder_deps="zlib" +ffv1_decoder_select="rangecoder" +ffv1_encoder_select="rangecoder" +ffvhuff_decoder_select="huffyuv_decoder" +ffvhuff_encoder_select="huffyuv_encoder" +fic_decoder_select="golomb" +flac_decoder_select="flacdsp" +flac_encoder_select="bswapdsp flacdsp lpc" +flashsv2_decoder_deps="zlib" +flashsv2_encoder_deps="zlib" +flashsv_decoder_deps="zlib" +flashsv_encoder_deps="zlib" +flv_decoder_select="h263_decoder" +flv_encoder_select="h263_encoder" +fourxm_decoder_select="blockdsp bswapdsp" +fraps_decoder_select="bswapdsp huffman" +g2m_decoder_deps="zlib" +g2m_decoder_select="blockdsp idctdsp jpegtables" +g729_decoder_select="audiodsp" +h261_decoder_select="mpegvideo" +h261_encoder_select="mpegvideoenc" +h263_decoder_select="h263_parser h263dsp mpegvideo qpeldsp" +h263_encoder_select="h263dsp mpegvideoenc" +h263i_decoder_select="h263_decoder" +h263p_decoder_select="h263_decoder" +h263p_encoder_select="h263_encoder" +h264_decoder_select="cabac golomb h264chroma h264dsp h264parse h264pred h264qpel videodsp" +h264_decoder_suggest="error_resilience" +hap_decoder_select="snappy texturedsp" +hap_encoder_deps="libsnappy" +hap_encoder_select="texturedspenc" +hevc_decoder_select="bswapdsp cabac golomb hevcparse videodsp" +huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" +huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" +hymt_decoder_select="huffyuv_decoder" +iac_decoder_select="imc_decoder" +imc_decoder_select="bswapdsp fft mdct sinewin" +indeo3_decoder_select="hpeldsp" +indeo4_decoder_select="ividsp" +indeo5_decoder_select="ividsp" +interplay_video_decoder_select="hpeldsp" +jpegls_decoder_select="mjpeg_decoder" +jv_decoder_select="blockdsp" +lagarith_decoder_select="llviddsp" +ljpeg_encoder_select="idctdsp jpegtables mpegvideoenc" +lscr_decoder_deps="zlib" +magicyuv_decoder_select="llviddsp" +magicyuv_encoder_select="llvidencdsp" +mdec_decoder_select="blockdsp idctdsp mpegvideo" +metasound_decoder_select="lsp mdct sinewin" +mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" +mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp jpegtables" +mjpeg_encoder_select="jpegtables mpegvideoenc" +mjpegb_decoder_select="mjpeg_decoder" +mlp_decoder_select="mlp_parser" +mlp_encoder_select="lpc audio_frame_queue" +motionpixels_decoder_select="bswapdsp" +mp1_decoder_select="mpegaudio" +mp1float_decoder_select="mpegaudio" +mp2_decoder_select="mpegaudio" +mp2float_decoder_select="mpegaudio" +mp3_decoder_select="mpegaudio" +mp3adu_decoder_select="mpegaudio" +mp3adufloat_decoder_select="mpegaudio" +mp3float_decoder_select="mpegaudio" +mp3on4_decoder_select="mpegaudio" +mp3on4float_decoder_select="mpegaudio" +mpc7_decoder_select="bswapdsp mpegaudiodsp" +mpc8_decoder_select="mpegaudiodsp" +mpegvideo_decoder_select="mpegvideo" +mpeg1video_decoder_select="mpegvideo" +mpeg1video_encoder_select="mpegvideoenc h263dsp" +mpeg2video_decoder_select="mpegvideo" +mpeg2video_encoder_select="mpegvideoenc h263dsp" +mpeg4_decoder_select="h263_decoder mpeg4video_parser" +mpeg4_encoder_select="h263_encoder" +msa1_decoder_select="mss34dsp" +mscc_decoder_deps="zlib" +msmpeg4v1_decoder_select="h263_decoder" +msmpeg4v2_decoder_select="h263_decoder" +msmpeg4v2_encoder_select="h263_encoder" +msmpeg4v3_decoder_select="h263_decoder" +msmpeg4v3_encoder_select="h263_encoder" +mss2_decoder_select="mpegvideo qpeldsp vc1_decoder" +mts2_decoder_select="mss34dsp" +mwsc_decoder_deps="zlib" +mxpeg_decoder_select="mjpeg_decoder" +nellymoser_decoder_select="mdct sinewin" +nellymoser_encoder_select="audio_frame_queue mdct sinewin" +nuv_decoder_select="idctdsp lzo" +on2avc_decoder_select="mdct" +opus_decoder_deps="swresample" +opus_decoder_select="mdct15" +opus_encoder_select="audio_frame_queue mdct15" +png_decoder_deps="zlib" +png_encoder_deps="zlib" +png_encoder_select="llvidencdsp" +prores_decoder_select="blockdsp idctdsp" +prores_encoder_select="fdctdsp" +qcelp_decoder_select="lsp" +qdm2_decoder_select="mdct rdft mpegaudiodsp" +ra_144_decoder_select="audiodsp" +ra_144_encoder_select="audio_frame_queue lpc audiodsp" +ralf_decoder_select="golomb" +rasc_decoder_deps="zlib" +rawvideo_decoder_select="bswapdsp" +rscc_decoder_deps="zlib" +rtjpeg_decoder_select="me_cmp" +rv10_decoder_select="h263_decoder" +rv10_encoder_select="h263_encoder" +rv20_decoder_select="h263_decoder" +rv20_encoder_select="h263_encoder" +rv30_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" +rv40_decoder_select="golomb h264pred h264qpel mpegvideo rv34dsp" +screenpresso_decoder_deps="zlib" +shorten_decoder_select="bswapdsp" +sipr_decoder_select="lsp" +snow_decoder_select="dwt h264qpel hpeldsp me_cmp rangecoder videodsp" +snow_encoder_select="dwt h264qpel hpeldsp me_cmp mpegvideoenc rangecoder" +sonic_decoder_select="golomb rangecoder" +sonic_encoder_select="golomb rangecoder" +sonic_ls_encoder_select="golomb rangecoder" +sp5x_decoder_select="mjpeg_decoder" +speedhq_decoder_select="mpegvideo" +srgc_decoder_deps="zlib" +svq1_decoder_select="hpeldsp" +svq1_encoder_select="hpeldsp me_cmp mpegvideoenc" +svq3_decoder_select="golomb h264dsp h264parse h264pred hpeldsp tpeldsp videodsp" +svq3_decoder_suggest="zlib" +tak_decoder_select="audiodsp" +tdsc_decoder_deps="zlib" +tdsc_decoder_select="mjpeg_decoder" +theora_decoder_select="vp3_decoder" +thp_decoder_select="mjpeg_decoder" +tiff_decoder_suggest="zlib lzma" +tiff_encoder_suggest="zlib" +truehd_decoder_select="mlp_parser" +truehd_encoder_select="lpc audio_frame_queue" +truemotion2_decoder_select="bswapdsp" +truespeech_decoder_select="bswapdsp" +tscc_decoder_deps="zlib" +twinvq_decoder_select="mdct lsp sinewin" +txd_decoder_select="texturedsp" +utvideo_decoder_select="bswapdsp llviddsp" +utvideo_encoder_select="bswapdsp huffman llvidencdsp" +vble_decoder_select="llviddsp" +vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideo vc1dsp" +vc1image_decoder_select="vc1_decoder" +vorbis_decoder_select="mdct" +vorbis_encoder_select="audio_frame_queue mdct" +vp3_decoder_select="hpeldsp vp3dsp videodsp" +vp4_decoder_select="vp3_decoder" +vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp vp56dsp" +vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp vp56dsp" +vp6a_decoder_select="vp6_decoder" +vp6f_decoder_select="vp6_decoder" +vp7_decoder_select="h264pred videodsp vp8dsp" +vp8_decoder_select="h264pred videodsp vp8dsp" +vp9_decoder_select="videodsp vp9_parser vp9_superframe_split_bsf" +wcmv_decoder_deps="zlib" +webp_decoder_select="vp8_decoder exif" +wmalossless_decoder_select="llauddsp" +wmapro_decoder_select="mdct sinewin wma_freqs" +wmav1_decoder_select="mdct sinewin wma_freqs" +wmav1_encoder_select="mdct sinewin wma_freqs" +wmav2_decoder_select="mdct sinewin wma_freqs" +wmav2_encoder_select="mdct sinewin wma_freqs" +wmavoice_decoder_select="lsp rdft dct mdct sinewin" +wmv1_decoder_select="h263_decoder" +wmv1_encoder_select="h263_encoder" +wmv2_decoder_select="blockdsp error_resilience h263_decoder idctdsp intrax8 videodsp wmv2dsp" +wmv2_encoder_select="h263_encoder wmv2dsp" +wmv3_decoder_select="vc1_decoder" +wmv3image_decoder_select="wmv3_decoder" +xma1_decoder_select="wmapro_decoder" +xma2_decoder_select="wmapro_decoder" +zerocodec_decoder_deps="zlib" +zlib_decoder_deps="zlib" +zlib_encoder_deps="zlib" +zmbv_decoder_deps="zlib" +zmbv_encoder_deps="zlib" + +# hardware accelerators +crystalhd_deps="libcrystalhd_libcrystalhd_if_h" +cuda_deps="ffnvcodec" +cuvid_deps="ffnvcodec" +d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" +dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" +ffnvcodec_deps_any="libdl LoadLibrary" +nvdec_deps="ffnvcodec" +vaapi_x11_deps="xlib" +videotoolbox_hwaccel_deps="videotoolbox pthreads" +videotoolbox_hwaccel_extralibs="-framework QuartzCore" +xvmc_deps="X11_extensions_XvMClib_h" + +h263_vaapi_hwaccel_deps="vaapi" +h263_vaapi_hwaccel_select="h263_decoder" +h263_videotoolbox_hwaccel_deps="videotoolbox" +h263_videotoolbox_hwaccel_select="h263_decoder" +h264_d3d11va_hwaccel_deps="d3d11va" +h264_d3d11va_hwaccel_select="h264_decoder" +h264_d3d11va2_hwaccel_deps="d3d11va" +h264_d3d11va2_hwaccel_select="h264_decoder" +h264_dxva2_hwaccel_deps="dxva2" +h264_dxva2_hwaccel_select="h264_decoder" +h264_nvdec_hwaccel_deps="nvdec" +h264_nvdec_hwaccel_select="h264_decoder" +h264_vaapi_hwaccel_deps="vaapi" +h264_vaapi_hwaccel_select="h264_decoder" +h264_vdpau_hwaccel_deps="vdpau" +h264_vdpau_hwaccel_select="h264_decoder" +h264_videotoolbox_hwaccel_deps="videotoolbox" +h264_videotoolbox_hwaccel_select="h264_decoder" +hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" +hevc_d3d11va_hwaccel_select="hevc_decoder" +hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" +hevc_d3d11va2_hwaccel_select="hevc_decoder" +hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" +hevc_dxva2_hwaccel_select="hevc_decoder" +hevc_nvdec_hwaccel_deps="nvdec" +hevc_nvdec_hwaccel_select="hevc_decoder" +hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC" +hevc_vaapi_hwaccel_select="hevc_decoder" +hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC" +hevc_vdpau_hwaccel_select="hevc_decoder" +hevc_videotoolbox_hwaccel_deps="videotoolbox" +hevc_videotoolbox_hwaccel_select="hevc_decoder" +mjpeg_nvdec_hwaccel_deps="nvdec" +mjpeg_nvdec_hwaccel_select="mjpeg_decoder" +mjpeg_vaapi_hwaccel_deps="vaapi" +mjpeg_vaapi_hwaccel_select="mjpeg_decoder" +mpeg_xvmc_hwaccel_deps="xvmc" +mpeg_xvmc_hwaccel_select="mpeg2video_decoder" +mpeg1_nvdec_hwaccel_deps="nvdec" +mpeg1_nvdec_hwaccel_select="mpeg1video_decoder" +mpeg1_vdpau_hwaccel_deps="vdpau" +mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" +mpeg1_videotoolbox_hwaccel_deps="videotoolbox" +mpeg1_videotoolbox_hwaccel_select="mpeg1video_decoder" +mpeg1_xvmc_hwaccel_deps="xvmc" +mpeg1_xvmc_hwaccel_select="mpeg1video_decoder" +mpeg2_d3d11va_hwaccel_deps="d3d11va" +mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" +mpeg2_d3d11va2_hwaccel_deps="d3d11va" +mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder" +mpeg2_dxva2_hwaccel_deps="dxva2" +mpeg2_dxva2_hwaccel_select="mpeg2video_decoder" +mpeg2_nvdec_hwaccel_deps="nvdec" +mpeg2_nvdec_hwaccel_select="mpeg2video_decoder" +mpeg2_vaapi_hwaccel_deps="vaapi" +mpeg2_vaapi_hwaccel_select="mpeg2video_decoder" +mpeg2_vdpau_hwaccel_deps="vdpau" +mpeg2_vdpau_hwaccel_select="mpeg2video_decoder" +mpeg2_videotoolbox_hwaccel_deps="videotoolbox" +mpeg2_videotoolbox_hwaccel_select="mpeg2video_decoder" +mpeg2_xvmc_hwaccel_deps="xvmc" +mpeg2_xvmc_hwaccel_select="mpeg2video_decoder" +mpeg4_nvdec_hwaccel_deps="nvdec" +mpeg4_nvdec_hwaccel_select="mpeg4_decoder" +mpeg4_vaapi_hwaccel_deps="vaapi" +mpeg4_vaapi_hwaccel_select="mpeg4_decoder" +mpeg4_vdpau_hwaccel_deps="vdpau" +mpeg4_vdpau_hwaccel_select="mpeg4_decoder" +mpeg4_videotoolbox_hwaccel_deps="videotoolbox" +mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" +vc1_d3d11va_hwaccel_deps="d3d11va" +vc1_d3d11va_hwaccel_select="vc1_decoder" +vc1_d3d11va2_hwaccel_deps="d3d11va" +vc1_d3d11va2_hwaccel_select="vc1_decoder" +vc1_dxva2_hwaccel_deps="dxva2" +vc1_dxva2_hwaccel_select="vc1_decoder" +vc1_nvdec_hwaccel_deps="nvdec" +vc1_nvdec_hwaccel_select="vc1_decoder" +vc1_vaapi_hwaccel_deps="vaapi" +vc1_vaapi_hwaccel_select="vc1_decoder" +vc1_vdpau_hwaccel_deps="vdpau" +vc1_vdpau_hwaccel_select="vc1_decoder" +vp8_nvdec_hwaccel_deps="nvdec" +vp8_nvdec_hwaccel_select="vp8_decoder" +vp8_vaapi_hwaccel_deps="vaapi" +vp8_vaapi_hwaccel_select="vp8_decoder" +vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" +vp9_d3d11va_hwaccel_select="vp9_decoder" +vp9_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_VP9" +vp9_d3d11va2_hwaccel_select="vp9_decoder" +vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" +vp9_dxva2_hwaccel_select="vp9_decoder" +vp9_nvdec_hwaccel_deps="nvdec" +vp9_nvdec_hwaccel_select="vp9_decoder" +vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" +vp9_vaapi_hwaccel_select="vp9_decoder" +wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" +wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" +wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" +wmv3_nvdec_hwaccel_select="vc1_nvdec_hwaccel" +wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" +wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" + +# hardware-accelerated codecs +omx_deps="libdl pthreads" +omx_rpi_select="omx" +qsv_deps="libmfx" +qsvdec_select="qsv" +qsvenc_select="qsv" +qsvvpp_select="qsv" +vaapi_encode_deps="vaapi" +v4l2_m2m_deps="linux_videodev2_h sem_timedwait" + +hwupload_cuda_filter_deps="ffnvcodec" +scale_npp_filter_deps="ffnvcodec libnpp" +scale_cuda_filter_deps="ffnvcodec" +scale_cuda_filter_deps_any="cuda_nvcc cuda_llvm" +thumbnail_cuda_filter_deps="ffnvcodec" +thumbnail_cuda_filter_deps_any="cuda_nvcc cuda_llvm" +transpose_npp_filter_deps="ffnvcodec libnpp" + +amf_deps_any="libdl LoadLibrary" +nvenc_deps="ffnvcodec" +nvenc_deps_any="libdl LoadLibrary" +nvenc_encoder_deps="nvenc" + +h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" +h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" +h264_amf_encoder_deps="amf" +h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" +h264_cuvid_decoder_deps="cuvid" +h264_cuvid_decoder_select="h264_mp4toannexb_bsf" +h264_mediacodec_decoder_deps="mediacodec" +h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser" +h264_mmal_decoder_deps="mmal" +h264_nvenc_encoder_deps="nvenc" +h264_omx_encoder_deps="omx" +h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec" +h264_qsv_encoder_select="qsvenc" +h264_rkmpp_decoder_deps="rkmpp" +h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" +h264_vaapi_encoder_select="cbs_h264 vaapi_encode" +h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" +h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf" +h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" +hevc_amf_encoder_deps="amf" +hevc_cuvid_decoder_deps="cuvid" +hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_mediacodec_decoder_deps="mediacodec" +hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" +hevc_nvenc_encoder_deps="nvenc" +hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec" +hevc_qsv_encoder_select="hevcparse qsvenc" +hevc_rkmpp_decoder_deps="rkmpp" +hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" +hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" +hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" +hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" +hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf" +hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" +mjpeg_cuvid_decoder_deps="cuvid" +mjpeg_qsv_encoder_deps="libmfx" +mjpeg_qsv_encoder_select="qsvenc" +mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" +mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode" +mpeg1_cuvid_decoder_deps="cuvid" +mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m" +mpeg2_crystalhd_decoder_select="crystalhd" +mpeg2_cuvid_decoder_deps="cuvid" +mpeg2_mmal_decoder_deps="mmal" +mpeg2_mediacodec_decoder_deps="mediacodec" +mpeg2_qsv_decoder_select="qsvdec mpegvideo_parser" +mpeg2_qsv_encoder_select="qsvenc" +mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" +mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" +mpeg4_crystalhd_decoder_select="crystalhd" +mpeg4_cuvid_decoder_deps="cuvid" +mpeg4_mediacodec_decoder_deps="mediacodec" +mpeg4_mmal_decoder_deps="mmal" +mpeg4_omx_encoder_deps="omx" +mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m" +mpeg4_v4l2m2m_encoder_deps="v4l2_m2m mpeg4_v4l2_m2m" +msmpeg4_crystalhd_decoder_select="crystalhd" +nvenc_h264_encoder_select="h264_nvenc_encoder" +nvenc_hevc_encoder_select="hevc_nvenc_encoder" +vc1_crystalhd_decoder_select="crystalhd" +vc1_cuvid_decoder_deps="cuvid" +vc1_mmal_decoder_deps="mmal" +vc1_qsv_decoder_select="qsvdec vc1_parser" +vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m" +vp8_cuvid_decoder_deps="cuvid" +vp8_mediacodec_decoder_deps="mediacodec" +vp8_qsv_decoder_select="qsvdec vp8_parser" +vp8_rkmpp_decoder_deps="rkmpp" +vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" +vp8_vaapi_encoder_select="vaapi_encode" +vp8_v4l2m2m_decoder_deps="v4l2_m2m vp8_v4l2_m2m" +vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m" +vp9_cuvid_decoder_deps="cuvid" +vp9_mediacodec_decoder_deps="mediacodec" +vp9_rkmpp_decoder_deps="rkmpp" +vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" +vp9_vaapi_encoder_select="vaapi_encode" +vp9_v4l2m2m_decoder_deps="v4l2_m2m vp9_v4l2_m2m" +wmv3_crystalhd_decoder_select="crystalhd" + +# parsers +aac_parser_select="adts_header" +av1_parser_select="cbs_av1" +h264_parser_select="golomb h264dsp h264parse" +hevc_parser_select="hevcparse" +mpegaudio_parser_select="mpegaudioheader" +mpegvideo_parser_select="mpegvideo" +mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" +vc1_parser_select="vc1dsp" + +# bitstream_filters +aac_adtstoasc_bsf_select="adts_header" +av1_frame_split_bsf_select="cbs_av1" +av1_metadata_bsf_select="cbs_av1" +eac3_core_bsf_select="ac3_parser" +filter_units_bsf_select="cbs" +h264_metadata_bsf_deps="const_nan" +h264_metadata_bsf_select="cbs_h264" +h264_redundant_pps_bsf_select="cbs_h264" +hevc_metadata_bsf_select="cbs_h265" +mjpeg2jpeg_bsf_select="jpegtables" +mpeg2_metadata_bsf_select="cbs_mpeg2" +trace_headers_bsf_select="cbs" +vp9_metadata_bsf_select="cbs_vp9" + +# external libraries +aac_at_decoder_deps="audiotoolbox" +aac_at_decoder_select="aac_adtstoasc_bsf" +ac3_at_decoder_deps="audiotoolbox" +ac3_at_decoder_select="ac3_parser" +adpcm_ima_qt_at_decoder_deps="audiotoolbox" +alac_at_decoder_deps="audiotoolbox" +amr_nb_at_decoder_deps="audiotoolbox" +avisynth_deps_any="libdl LoadLibrary" +avisynth_demuxer_deps="avisynth" +avisynth_demuxer_select="riffdec" +eac3_at_decoder_deps="audiotoolbox" +eac3_at_decoder_select="ac3_parser" +gsm_ms_at_decoder_deps="audiotoolbox" +ilbc_at_decoder_deps="audiotoolbox" +mp1_at_decoder_deps="audiotoolbox" +mp2_at_decoder_deps="audiotoolbox" +mp3_at_decoder_deps="audiotoolbox" +mp1_at_decoder_select="mpegaudioheader" +mp2_at_decoder_select="mpegaudioheader" +mp3_at_decoder_select="mpegaudioheader" +pcm_alaw_at_decoder_deps="audiotoolbox" +pcm_mulaw_at_decoder_deps="audiotoolbox" +qdmc_at_decoder_deps="audiotoolbox" +qdm2_at_decoder_deps="audiotoolbox" +aac_at_encoder_deps="audiotoolbox" +aac_at_encoder_select="audio_frame_queue" +alac_at_encoder_deps="audiotoolbox" +alac_at_encoder_select="audio_frame_queue" +ilbc_at_encoder_deps="audiotoolbox" +ilbc_at_encoder_select="audio_frame_queue" +pcm_alaw_at_encoder_deps="audiotoolbox" +pcm_alaw_at_encoder_select="audio_frame_queue" +pcm_mulaw_at_encoder_deps="audiotoolbox" +pcm_mulaw_at_encoder_select="audio_frame_queue" +chromaprint_muxer_deps="chromaprint" +h264_videotoolbox_encoder_deps="pthreads" +h264_videotoolbox_encoder_select="videotoolbox_encoder" +hevc_videotoolbox_encoder_deps="pthreads" +hevc_videotoolbox_encoder_select="videotoolbox_encoder" +libaom_av1_decoder_deps="libaom" +libaom_av1_encoder_deps="libaom" +libaom_av1_encoder_select="extract_extradata_bsf" +libaribb24_decoder_deps="libaribb24" +libcelt_decoder_deps="libcelt" +libcodec2_decoder_deps="libcodec2" +libcodec2_encoder_deps="libcodec2" +libdav1d_decoder_deps="libdav1d" +libdavs2_decoder_deps="libdavs2" +libfdk_aac_decoder_deps="libfdk_aac" +libfdk_aac_encoder_deps="libfdk_aac" +libfdk_aac_encoder_select="audio_frame_queue" +libgme_demuxer_deps="libgme" +libgsm_decoder_deps="libgsm" +libgsm_encoder_deps="libgsm" +libgsm_ms_decoder_deps="libgsm" +libgsm_ms_encoder_deps="libgsm" +libilbc_decoder_deps="libilbc" +libilbc_encoder_deps="libilbc" +libkvazaar_encoder_deps="libkvazaar" +libmodplug_demuxer_deps="libmodplug" +libmp3lame_encoder_deps="libmp3lame" +libmp3lame_encoder_select="audio_frame_queue mpegaudioheader" +libopencore_amrnb_decoder_deps="libopencore_amrnb" +libopencore_amrnb_encoder_deps="libopencore_amrnb" +libopencore_amrnb_encoder_select="audio_frame_queue" +libopencore_amrwb_decoder_deps="libopencore_amrwb" +libopenh264_decoder_deps="libopenh264" +libopenh264_decoder_select="h264_mp4toannexb_bsf" +libopenh264_encoder_deps="libopenh264" +libopenjpeg_decoder_deps="libopenjpeg" +libopenjpeg_encoder_deps="libopenjpeg" +libopenmpt_demuxer_deps="libopenmpt" +libopus_decoder_deps="libopus" +libopus_encoder_deps="libopus" +libopus_encoder_select="audio_frame_queue" +librsvg_decoder_deps="librsvg" +libshine_encoder_deps="libshine" +libshine_encoder_select="audio_frame_queue" +libspeex_decoder_deps="libspeex" +libspeex_encoder_deps="libspeex" +libspeex_encoder_select="audio_frame_queue" +libtheora_encoder_deps="libtheora" +libtwolame_encoder_deps="libtwolame" +libvo_amrwbenc_encoder_deps="libvo_amrwbenc" +libvorbis_decoder_deps="libvorbis" +libvorbis_encoder_deps="libvorbis libvorbisenc" +libvorbis_encoder_select="audio_frame_queue" +libvpx_vp8_decoder_deps="libvpx" +libvpx_vp8_encoder_deps="libvpx" +libvpx_vp9_decoder_deps="libvpx" +libvpx_vp9_encoder_deps="libvpx" +libwavpack_encoder_deps="libwavpack" +libwavpack_encoder_select="audio_frame_queue" +libwebp_encoder_deps="libwebp" +libwebp_anim_encoder_deps="libwebp" +libx262_encoder_deps="libx262" +libx264_encoder_deps="libx264" +libx264rgb_encoder_deps="libx264 x264_csp_bgr" +libx264rgb_encoder_select="libx264_encoder" +libx265_encoder_deps="libx265" +libxavs_encoder_deps="libxavs" +libxavs2_encoder_deps="libxavs2" +libxvid_encoder_deps="libxvid" +libzvbi_teletext_decoder_deps="libzvbi" +vapoursynth_demuxer_deps="vapoursynth" +videotoolbox_suggest="coreservices" +videotoolbox_deps="corefoundation coremedia corevideo" +videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames" + +# demuxers / muxers +ac3_demuxer_select="ac3_parser" +aiff_muxer_select="iso_media" +asf_demuxer_select="riffdec" +asf_o_demuxer_select="riffdec" +asf_muxer_select="riffenc" +asf_stream_muxer_select="asf_muxer" +avi_demuxer_select="iso_media riffdec exif" +avi_muxer_select="riffenc" +caf_demuxer_select="iso_media riffdec" +caf_muxer_select="iso_media" +dash_muxer_select="mp4_muxer" +dash_demuxer_deps="libxml2" +dirac_demuxer_select="dirac_parser" +dts_demuxer_select="dca_parser" +dtshd_demuxer_select="dca_parser" +dv_demuxer_select="dvprofile" +dv_muxer_select="dvprofile" +dxa_demuxer_select="riffdec" +eac3_demuxer_select="ac3_parser" +f4v_muxer_select="mov_muxer" +fifo_muxer_deps="threads" +flac_demuxer_select="flac_parser" +hds_muxer_select="flv_muxer" +hls_muxer_select="mpegts_muxer" +hls_muxer_suggest="gcrypt openssl" +image2_alias_pix_demuxer_select="image2_demuxer" +image2_brender_pix_demuxer_select="image2_demuxer" +ipod_muxer_select="mov_muxer" +ismv_muxer_select="mov_muxer" +ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" +matroska_audio_muxer_select="matroska_muxer" +matroska_demuxer_select="iso_media riffdec" +matroska_demuxer_suggest="bzlib lzo zlib" +matroska_muxer_select="iso_media riffenc" +mmf_muxer_select="riffenc" +mov_demuxer_select="iso_media riffdec" +mov_demuxer_suggest="zlib" +mov_muxer_select="iso_media riffenc rtpenc_chain" +mp3_demuxer_select="mpegaudio_parser" +mp3_muxer_select="mpegaudioheader" +mp4_muxer_select="mov_muxer" +mpegts_demuxer_select="iso_media" +mpegts_muxer_select="adts_muxer latm_muxer" +mpegtsraw_demuxer_select="mpegts_demuxer" +mxf_d10_muxer_select="mxf_muxer" +mxf_opatom_muxer_select="mxf_muxer" +nut_muxer_select="riffenc" +nuv_demuxer_select="riffdec" +oga_muxer_select="ogg_muxer" +ogg_demuxer_select="dirac_parse" +ogv_muxer_select="ogg_muxer" +opus_muxer_select="ogg_muxer" +psp_muxer_select="mov_muxer" +rtp_demuxer_select="sdp_demuxer" +rtp_muxer_select="golomb" +rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" +rtsp_demuxer_select="http_protocol rtpdec" +rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" +sap_demuxer_select="sdp_demuxer" +sap_muxer_select="rtp_muxer rtp_protocol rtpenc_chain" +sdp_demuxer_select="rtpdec" +smoothstreaming_muxer_select="ismv_muxer" +spdif_demuxer_select="adts_header" +spdif_muxer_select="adts_header" +spx_muxer_select="ogg_muxer" +swf_demuxer_suggest="zlib" +tak_demuxer_select="tak_parser" +tg2_muxer_select="mov_muxer" +tgp_muxer_select="mov_muxer" +vobsub_demuxer_select="mpegps_demuxer" +w64_demuxer_select="wav_demuxer" +w64_muxer_select="wav_muxer" +wav_demuxer_select="riffdec" +wav_muxer_select="riffenc" +webm_muxer_select="iso_media riffenc" +webm_dash_manifest_demuxer_select="matroska_demuxer" +wtv_demuxer_select="mpegts_demuxer riffdec" +wtv_muxer_select="mpegts_muxer riffenc" +xmv_demuxer_select="riffdec" +xwma_demuxer_select="riffdec" + +# indevs / outdevs +android_camera_indev_deps="android camera2ndk mediandk pthreads" +android_camera_indev_extralibs="-landroid -lcamera2ndk -lmediandk" +alsa_indev_deps="alsa" +alsa_outdev_deps="alsa" +avfoundation_indev_deps="avfoundation corevideo coremedia pthreads" +avfoundation_indev_suggest="coregraphics applicationservices" +avfoundation_indev_extralibs="-framework Foundation" +bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" +caca_outdev_deps="libcaca" +decklink_deps_any="libdl LoadLibrary" +decklink_indev_deps="decklink threads" +decklink_indev_extralibs="-lstdc++" +decklink_outdev_deps="decklink threads" +decklink_outdev_suggest="libklvanc" +decklink_outdev_extralibs="-lstdc++" +dshow_indev_deps="IBaseFilter" +dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid -loleaut32 -lshlwapi" +fbdev_indev_deps="linux_fb_h" +fbdev_outdev_deps="linux_fb_h" +gdigrab_indev_deps="CreateDIBSection" +gdigrab_indev_extralibs="-lgdi32" +gdigrab_indev_select="bmp_decoder" +iec61883_indev_deps="libiec61883" +jack_indev_deps="libjack" +jack_indev_deps_any="sem_timedwait dispatch_dispatch_h" +kmsgrab_indev_deps="libdrm" +lavfi_indev_deps="avfilter" +libcdio_indev_deps="libcdio" +libdc1394_indev_deps="libdc1394" +openal_indev_deps="openal" +opengl_outdev_deps="opengl" +opengl_outdev_suggest="sdl2" +oss_indev_deps_any="sys_soundcard_h" +oss_outdev_deps_any="sys_soundcard_h" +pulse_indev_deps="libpulse" +pulse_outdev_deps="libpulse" +sdl2_outdev_deps="sdl2" +sndio_indev_deps="sndio" +sndio_outdev_deps="sndio" +v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" +v4l2_indev_suggest="libv4l2" +v4l2_outdev_deps_any="linux_videodev2_h sys_videoio_h" +v4l2_outdev_suggest="libv4l2" +vfwcap_indev_deps="vfw32 vfwcap_defines" +xcbgrab_indev_deps="libxcb" +xcbgrab_indev_suggest="libxcb_shm libxcb_shape libxcb_xfixes" +xv_outdev_deps="xlib" + +# protocols +async_protocol_deps="threads" +bluray_protocol_deps="libbluray" +ffrtmpcrypt_protocol_conflict="librtmp_protocol" +ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl mbedtls" +ffrtmpcrypt_protocol_select="tcp_protocol" +ffrtmphttp_protocol_conflict="librtmp_protocol" +ffrtmphttp_protocol_select="http_protocol" +ftp_protocol_select="tcp_protocol" +gopher_protocol_select="network" +http_protocol_select="tcp_protocol" +http_protocol_suggest="zlib" +httpproxy_protocol_select="tcp_protocol" +httpproxy_protocol_suggest="zlib" +https_protocol_select="tls_protocol" +https_protocol_suggest="zlib" +icecast_protocol_select="http_protocol" +mmsh_protocol_select="http_protocol" +mmst_protocol_select="network" +rtmp_protocol_conflict="librtmp_protocol" +rtmp_protocol_select="tcp_protocol" +rtmp_protocol_suggest="zlib" +rtmpe_protocol_select="ffrtmpcrypt_protocol" +rtmpe_protocol_suggest="zlib" +rtmps_protocol_conflict="librtmp_protocol" +rtmps_protocol_select="tls_protocol" +rtmps_protocol_suggest="zlib" +rtmpt_protocol_select="ffrtmphttp_protocol" +rtmpt_protocol_suggest="zlib" +rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" +rtmpte_protocol_suggest="zlib" +rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" +rtmpts_protocol_suggest="zlib" +rtp_protocol_select="udp_protocol" +schannel_conflict="openssl gnutls libtls mbedtls" +sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags" +sctp_protocol_select="network" +securetransport_conflict="openssl gnutls libtls mbedtls" +srtp_protocol_select="rtp_protocol srtp" +tcp_protocol_select="network" +tls_protocol_deps_any="gnutls openssl schannel securetransport libtls mbedtls" +tls_protocol_select="tcp_protocol" +udp_protocol_select="network" +udplite_protocol_select="network" +unix_protocol_deps="sys_un_h" +unix_protocol_select="network" + +# external library protocols +librtmp_protocol_deps="librtmp" +librtmpe_protocol_deps="librtmp" +librtmps_protocol_deps="librtmp" +librtmpt_protocol_deps="librtmp" +librtmpte_protocol_deps="librtmp" +libsmbclient_protocol_deps="libsmbclient gplv3" +libsrt_protocol_deps="libsrt" +libsrt_protocol_select="network" +libssh_protocol_deps="libssh" +libtls_conflict="openssl gnutls mbedtls" + +# filters +afftdn_filter_deps="avcodec" +afftdn_filter_select="fft" +afftfilt_filter_deps="avcodec" +afftfilt_filter_select="fft" +afir_filter_deps="avcodec" +afir_filter_select="fft" +amovie_filter_deps="avcodec avformat" +aresample_filter_deps="swresample" +asr_filter_deps="pocketsphinx" +ass_filter_deps="libass" +atempo_filter_deps="avcodec" +atempo_filter_select="rdft" +avgblur_opencl_filter_deps="opencl" +azmq_filter_deps="libzmq" +blackframe_filter_deps="gpl" +bm3d_filter_deps="avcodec" +bm3d_filter_select="dct" +boxblur_filter_deps="gpl" +boxblur_opencl_filter_deps="opencl gpl" +bs2b_filter_deps="libbs2b" +colorkey_opencl_filter_deps="opencl" +colormatrix_filter_deps="gpl" +convolution_opencl_filter_deps="opencl" +convolve_filter_deps="avcodec" +convolve_filter_select="fft" +coreimage_filter_deps="coreimage appkit" +coreimage_filter_extralibs="-framework OpenGL" +coreimagesrc_filter_deps="coreimage appkit" +coreimagesrc_filter_extralibs="-framework OpenGL" +cover_rect_filter_deps="avcodec avformat gpl" +cropdetect_filter_deps="gpl" +deconvolve_filter_deps="avcodec" +deconvolve_filter_select="fft" +deinterlace_qsv_filter_deps="libmfx" +deinterlace_vaapi_filter_deps="vaapi" +delogo_filter_deps="gpl" +denoise_vaapi_filter_deps="vaapi" +derain_filter_select="dnn" +deshake_filter_select="pixelutils" +dilation_opencl_filter_deps="opencl" +drawtext_filter_deps="libfreetype" +drawtext_filter_suggest="libfontconfig libfribidi" +elbg_filter_deps="avcodec" +eq_filter_deps="gpl" +erosion_opencl_filter_deps="opencl" +fftfilt_filter_deps="avcodec" +fftfilt_filter_select="rdft" +fftdnoiz_filter_deps="avcodec" +fftdnoiz_filter_select="fft" +find_rect_filter_deps="avcodec avformat gpl" +firequalizer_filter_deps="avcodec" +firequalizer_filter_select="rdft" +flite_filter_deps="libflite" +framerate_filter_select="scene_sad" +freezedetect_filter_select="scene_sad" +frei0r_filter_deps="frei0r libdl" +frei0r_src_filter_deps="frei0r libdl" +fspp_filter_deps="gpl" +geq_filter_deps="gpl" +histeq_filter_deps="gpl" +hqdn3d_filter_deps="gpl" +interlace_filter_deps="gpl" +kerndeint_filter_deps="gpl" +ladspa_filter_deps="ladspa libdl" +lensfun_filter_deps="liblensfun version3" +lv2_filter_deps="lv2" +mcdeint_filter_deps="avcodec gpl" +movie_filter_deps="avcodec avformat" +mpdecimate_filter_deps="gpl" +mpdecimate_filter_select="pixelutils" +minterpolate_filter_select="scene_sad" +mptestsrc_filter_deps="gpl" +negate_filter_deps="lut_filter" +nlmeans_opencl_filter_deps="opencl" +nnedi_filter_deps="gpl" +ocr_filter_deps="libtesseract" +ocv_filter_deps="libopencv" +openclsrc_filter_deps="opencl" +overlay_opencl_filter_deps="opencl" +overlay_qsv_filter_deps="libmfx" +overlay_qsv_filter_select="qsvvpp" +owdenoise_filter_deps="gpl" +pan_filter_deps="swresample" +perspective_filter_deps="gpl" +phase_filter_deps="gpl" +pp7_filter_deps="gpl" +pp_filter_deps="gpl postproc" +prewitt_opencl_filter_deps="opencl" +procamp_vaapi_filter_deps="vaapi" +program_opencl_filter_deps="opencl" +pullup_filter_deps="gpl" +removelogo_filter_deps="avcodec avformat swscale" +repeatfields_filter_deps="gpl" +resample_filter_deps="avresample" +roberts_opencl_filter_deps="opencl" +rubberband_filter_deps="librubberband" +sab_filter_deps="gpl swscale" +scale2ref_filter_deps="swscale" +scale_filter_deps="swscale" +scale_qsv_filter_deps="libmfx" +select_filter_select="scene_sad" +sharpness_vaapi_filter_deps="vaapi" +showcqt_filter_deps="avcodec avformat swscale" +showcqt_filter_suggest="libfontconfig libfreetype" +showcqt_filter_select="fft" +showfreqs_filter_deps="avcodec" +showfreqs_filter_select="fft" +showspectrum_filter_deps="avcodec" +showspectrum_filter_select="fft" +showspectrumpic_filter_deps="avcodec" +showspectrumpic_filter_select="fft" +signature_filter_deps="gpl avcodec avformat" +smartblur_filter_deps="gpl swscale" +sobel_opencl_filter_deps="opencl" +sofalizer_filter_deps="libmysofa avcodec" +sofalizer_filter_select="fft" +spectrumsynth_filter_deps="avcodec" +spectrumsynth_filter_select="fft" +spp_filter_deps="gpl avcodec" +spp_filter_select="fft idctdsp fdctdsp me_cmp pixblockdsp" +sr_filter_deps="avformat swscale" +sr_filter_select="dnn" +stereo3d_filter_deps="gpl" +subtitles_filter_deps="avformat avcodec libass" +super2xsai_filter_deps="gpl" +pixfmts_super2xsai_test_deps="super2xsai_filter" +tinterlace_filter_deps="gpl" +tinterlace_merge_test_deps="tinterlace_filter" +tinterlace_pad_test_deps="tinterlace_filter" +tonemap_filter_deps="const_nan" +tonemap_opencl_filter_deps="opencl const_nan" +transpose_opencl_filter_deps="opencl" +transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" +unsharp_opencl_filter_deps="opencl" +uspp_filter_deps="gpl avcodec" +vaguedenoiser_filter_deps="gpl" +vidstabdetect_filter_deps="libvidstab" +vidstabtransform_filter_deps="libvidstab" +libvmaf_filter_deps="libvmaf pthreads" +zmq_filter_deps="libzmq" +zoompan_filter_deps="swscale" +zscale_filter_deps="libzimg const_nan" +scale_vaapi_filter_deps="vaapi" +vpp_qsv_filter_deps="libmfx" +vpp_qsv_filter_select="qsvvpp" +yadif_cuda_filter_deps="ffnvcodec" +yadif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" + +# examples +avio_dir_cmd_deps="avformat avutil" +avio_reading_deps="avformat avcodec avutil" +decode_audio_example_deps="avcodec avutil" +decode_video_example_deps="avcodec avutil" +demuxing_decoding_example_deps="avcodec avformat avutil" +encode_audio_example_deps="avcodec avutil" +encode_video_example_deps="avcodec avutil" +extract_mvs_example_deps="avcodec avformat avutil" +filter_audio_example_deps="avfilter avutil" +filtering_audio_example_deps="avfilter avcodec avformat avutil" +filtering_video_example_deps="avfilter avcodec avformat avutil" +http_multiclient_example_deps="avformat avutil fork" +hw_decode_example_deps="avcodec avformat avutil" +metadata_example_deps="avformat avutil" +muxing_example_deps="avcodec avformat avutil swscale" +qsvdec_example_deps="avcodec avutil libmfx h264_qsv_decoder" +remuxing_example_deps="avcodec avformat avutil" +resampling_audio_example_deps="avutil swresample" +scaling_video_example_deps="avutil swscale" +transcode_aac_example_deps="avcodec avformat swresample" +transcoding_example_deps="avfilter avcodec avformat avutil" +vaapi_encode_example_deps="avcodec avutil h264_vaapi_encoder" +vaapi_transcode_example_deps="avcodec avformat avutil h264_vaapi_encoder" + +# EXTRALIBS_LIST +cpu_init_extralibs="pthreads_extralibs" +cws2fws_extralibs="zlib_extralibs" + +# libraries, in any order +avcodec_deps="avutil" +avcodec_suggest="libm" +avcodec_select="null_bsf" +avdevice_deps="avformat avcodec avutil" +avdevice_suggest="libm" +avfilter_deps="avutil" +avfilter_suggest="libm" +avformat_deps="avcodec avutil" +avformat_suggest="libm network zlib" +avresample_deps="avutil" +avresample_suggest="libm" +avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia bcrypt" +postproc_deps="avutil gpl" +postproc_suggest="libm" +swresample_deps="avutil" +swresample_suggest="libm libsoxr" +swscale_deps="avutil" +swscale_suggest="libm" + +avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs" +avfilter_extralibs="pthreads_extralibs" +avutil_extralibs="d3d11va_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs" + +# programs +ffmpeg_deps="avcodec avfilter avformat" +ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter + hflip_filter null_filter + transpose_filter trim_filter vflip_filter" +ffmpeg_suggest="ole32 psapi shell32" +ffplay_deps="avcodec avformat swscale swresample sdl2" +ffplay_select="rdft crop_filter transpose_filter hflip_filter vflip_filter rotate_filter" +ffplay_suggest="shell32" +ffprobe_deps="avcodec avformat" +ffprobe_suggest="shell32" + +# documentation +podpages_deps="perl" +manpages_deps="perl pod2man" +htmlpages_deps="perl" +htmlpages_deps_any="makeinfo_html texi2html" +txtpages_deps="perl makeinfo" +doc_deps_any="manpages htmlpages podpages txtpages" + +# default parameters + +logfile="ffbuild/config.log" + +# installation paths +prefix_default="/usr/local" +bindir_default='${prefix}/bin' +datadir_default='${prefix}/share/ffmpeg' +docdir_default='${prefix}/share/doc/ffmpeg' +incdir_default='${prefix}/include' +libdir_default='${prefix}/lib' +mandir_default='${prefix}/share/man' + +# toolchain +ar_default="ar" +cc_default="gcc" +cxx_default="g++" +host_cc_default="gcc" +doxygen_default="doxygen" +install="install" +ln_s_default="ln -s -f" +nm_default="nm -g" +pkg_config_default=pkg-config +ranlib_default="ranlib" +strip_default="strip" +version_script='--version-script' +objformat="elf32" +x86asmexe_default="nasm" +windres_default="windres" +striptype="direct" + +# OS +target_os_default=$(tolower $(uname -s)) +host_os=$target_os_default + +# machine +if test "$target_os_default" = aix; then + arch_default=$(uname -p) + strip_default="strip -X32_64" + nm_default="nm -g -X32_64" +else + arch_default=$(uname -m) +fi +cpu="generic" +intrinsics="none" + +# configurable options +enable $PROGRAM_LIST +enable $DOCUMENT_LIST +enable $EXAMPLE_LIST +enable $(filter_out avresample $LIBRARY_LIST) +enable stripping + +enable asm +enable debug +enable doc +enable faan faandct faanidct +enable optimizations +enable runtime_cpudetect +enable safe_bitstream_reader +enable static +enable swscale_alpha +enable valgrind_backtrace + +sws_max_filter_size_default=256 +set_default sws_max_filter_size + +# internal components are enabled by default +enable $EXTRALIBS_LIST + +# Avoid external, non-system, libraries getting enabled by dependency resolution +disable $EXTERNAL_LIBRARY_LIST $HWACCEL_LIBRARY_LIST + +# build settings +SHFLAGS='-shared -Wl,-soname,$$(@F)' +LIBPREF="lib" +LIBSUF=".a" +FULLNAME='$(NAME)$(BUILDSUF)' +LIBNAME='$(LIBPREF)$(FULLNAME)$(LIBSUF)' +SLIBPREF="lib" +SLIBSUF=".so" +SLIBNAME='$(SLIBPREF)$(FULLNAME)$(SLIBSUF)' +SLIBNAME_WITH_VERSION='$(SLIBNAME).$(LIBVERSION)' +SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' +LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"' +SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' +SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)' +VERSION_SCRIPT_POSTPROCESS_CMD="cat" + +asflags_filter=echo +cflags_filter=echo +ldflags_filter=echo + +AS_C='-c' +AS_O='-o $@' +CC_C='-c' +CC_E='-E -o $@' +CC_O='-o $@' +CXX_C='-c' +CXX_O='-o $@' +OBJCC_C='-c' +OBJCC_E='-E -o $@' +OBJCC_O='-o $@' +X86ASM_O='-o $@' +LD_O='-o $@' +LD_LIB='-l%' +LD_PATH='-L' +HOSTCC_C='-c' +HOSTCC_E='-E -o $@' +HOSTCC_O='-o $@' +HOSTLD_O='-o $@' +NVCC_C='-c' +NVCC_O='-o $@' + +host_extralibs='-lm' +host_cflags_filter=echo +host_ldflags_filter=echo + +target_path='$(CURDIR)' + +# since the object filename is not given with the -MM flag, the compiler +# is only able to print the basename, and we must add the path ourselves +DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>/dev/null | sed -e "/^\#.*/d" -e "s,^[[:space:]]*$(@F),$(@D)/$(@F)," > $(@:.o=.d)' +DEPFLAGS='-MM' + +mkdir -p ffbuild + +# find source path +if test -f configure; then + source_path=. +elif test -f src/configure; then + source_path=src +else + source_path=$(cd $(dirname "$0"); pwd) + case "$source_path" in + *[[:blank:]]*) die "Out of tree builds are impossible with whitespace in source path." ;; + esac + test -e "$source_path/config.h" && + die "Out of tree builds are impossible with config.h in source dir." +fi + +for v in "$@"; do + r=${v#*=} + l=${v%"$r"} + r=$(sh_quote "$r") + FFMPEG_CONFIGURATION="${FFMPEG_CONFIGURATION# } ${l}${r}" +done + +find_things_extern(){ + thing=$1 + pattern=$2 + file=$source_path/$3 + out=${4:-$thing} + sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file" +} + +find_filters_extern(){ + file=$source_path/$1 + sed -n 's/^extern AVFilter ff_[avfsinkrc]\{2,5\}_\([[:alnum:]_]\{1,\}\);/\1_filter/p' $file +} + +FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c) +OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev) +INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev) +MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c) +DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c) +ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c) +DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c) +CODEC_LIST=" + $ENCODER_LIST + $DECODER_LIST +" +PARSER_LIST=$(find_things_extern parser AVCodecParser libavcodec/parsers.c) +BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) +HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) +PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) + +AVCODEC_COMPONENTS_LIST=" + $BSF_LIST + $DECODER_LIST + $ENCODER_LIST + $HWACCEL_LIST + $PARSER_LIST +" + +AVDEVICE_COMPONENTS_LIST=" + $INDEV_LIST + $OUTDEV_LIST +" + +AVFILTER_COMPONENTS_LIST=" + $FILTER_LIST +" + +AVFORMAT_COMPONENTS_LIST=" + $DEMUXER_LIST + $MUXER_LIST + $PROTOCOL_LIST +" + +ALL_COMPONENTS=" + $AVCODEC_COMPONENTS_LIST + $AVDEVICE_COMPONENTS_LIST + $AVFILTER_COMPONENTS_LIST + $AVFORMAT_COMPONENTS_LIST +" + +for n in $COMPONENT_LIST; do + v=$(toupper ${n%s})_LIST + eval enable \$$v + eval ${n}_if_any="\$$v" +done + +enable $ARCH_EXT_LIST + +die_unknown(){ + echo "Unknown option \"$1\"." + echo "See $0 --help for available options." + exit 1 +} + +print_in_columns() { + tr ' ' '\n' | sort | tr '\r\n' ' ' | awk -v col_width=24 -v width="$ncols" ' + { + num_cols = width > col_width ? int(width / col_width) : 1; + num_rows = int((NF + num_cols-1) / num_cols); + y = x = 1; + for (y = 1; y <= num_rows; y++) { + i = y; + for (x = 1; x <= num_cols; x++) { + if (i <= NF) { + line = sprintf("%s%-" col_width "s", line, $i); + } + i = i + num_rows; + } + print line; line = ""; + } + }' | sed 's/ *$//' +} + +show_list() { + suffix=_$1 + shift + echo $* | sed s/$suffix//g | print_in_columns + exit 0 +} + +rand_list(){ + IFS=', ' + set -- $* + unset IFS + for thing; do + comp=${thing%:*} + prob=${thing#$comp} + prob=${prob#:} + is_in ${comp} $COMPONENT_LIST && eval comp=\$$(toupper ${comp%s})_LIST + echo "prob ${prob:-0.5}" + printf '%s\n' $comp + done +} + +do_random(){ + action=$1 + shift + random_seed=$(awk "BEGIN { srand($random_seed); print srand() }") + $action $(rand_list "$@" | awk "BEGIN { srand($random_seed) } \$1 == \"prob\" { prob = \$2; next } rand() < prob { print }") +} + +for opt do + optval="${opt#*=}" + case "$opt" in + --extra-ldflags=*) + add_ldflags $optval + ;; + --extra-ldexeflags=*) + add_ldexeflags $optval + ;; + --extra-ldsoflags=*) + add_ldsoflags $optval + ;; + --extra-ldlibflags=*) + warn "The --extra-ldlibflags option is only provided for compatibility and will be\n"\ + "removed in the future. Use --extra-ldsoflags instead." + add_ldsoflags $optval + ;; + --extra-libs=*) + add_extralibs $optval + ;; + --disable-devices) + disable $INDEV_LIST $OUTDEV_LIST + ;; + --enable-debug=*) + debuglevel="$optval" + ;; + --disable-programs) + disable $PROGRAM_LIST + ;; + --disable-everything) + map 'eval unset \${$(toupper ${v%s})_LIST}' $COMPONENT_LIST + ;; + --disable-all) + map 'eval unset \${$(toupper ${v%s})_LIST}' $COMPONENT_LIST + disable $LIBRARY_LIST $PROGRAM_LIST doc + enable avutil + ;; + --enable-random|--disable-random) + action=${opt%%-random} + do_random ${action#--} $COMPONENT_LIST + ;; + --enable-random=*|--disable-random=*) + action=${opt%%-random=*} + do_random ${action#--} $optval + ;; + --enable-sdl) + enable sdl2 + ;; + --enable-*=*|--disable-*=*) + eval $(echo "${opt%%=*}" | sed 's/--/action=/;s/-/ thing=/') + is_in "${thing}s" $COMPONENT_LIST || die_unknown "$opt" + eval list=\$$(toupper $thing)_LIST + name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing} + list=$(filter "$name" $list) + [ "$list" = "" ] && warn "Option $opt did not match anything" + test $action = enable && warn_if_gets_disabled $list + $action $list + ;; + --enable-yasm|--disable-yasm) + warn "The ${opt} option is only provided for compatibility and will be\n"\ + "removed in the future. Use --enable-x86asm / --disable-x86asm instead." + test $opt = --enable-yasm && x86asm=yes || x86asm=no + ;; + --yasmexe=*) + warn "The --yasmexe option is only provided for compatibility and will be\n"\ + "removed in the future. Use --x86asmexe instead." + x86asmexe="$optval" + ;; + --enable-?*|--disable-?*) + eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g') + if is_in $option $COMPONENT_LIST; then + test $action = disable && action=unset + eval $action \$$(toupper ${option%s})_LIST + elif is_in $option $CMDLINE_SELECT; then + $action $option + else + die_unknown $opt + fi + ;; + --list-*) + NAME="${opt#--list-}" + is_in $NAME $COMPONENT_LIST || die_unknown $opt + NAME=${NAME%s} + eval show_list $NAME \$$(toupper $NAME)_LIST + ;; + --help|-h) show_help + ;; + --quiet|-q) quiet=yes + ;; + --fatal-warnings) enable fatal_warnings + ;; + --libfuzzer=*) + libfuzzer_path="$optval" + ;; + *) + optname="${opt%%=*}" + optname="${optname#--}" + optname=$(echo "$optname" | sed 's/-/_/g') + if is_in $optname $CMDLINE_SET; then + eval $optname='$optval' + elif is_in $optname $CMDLINE_APPEND; then + append $optname "$optval" + else + die_unknown $opt + fi + ;; + esac +done + +for e in $env; do + eval "export $e" +done + +if disabled autodetect; then + + # Unless iconv is explicitely disabled by the user, we still want to probe + # for the iconv from the libc. + disabled iconv || enable libc_iconv + + disable_weak $EXTERNAL_AUTODETECT_LIBRARY_LIST + disable_weak $HWACCEL_AUTODETECT_LIBRARY_LIST +fi +# Mark specifically enabled, but normally autodetected libraries as requested. +for lib in $AUTODETECT_LIBS; do + enabled $lib && request $lib +done +#TODO: switch to $AUTODETECT_LIBS when $THREADS_LIST is supported the same way +enable_weak $EXTERNAL_AUTODETECT_LIBRARY_LIST +enable_weak $HWACCEL_AUTODETECT_LIBRARY_LIST + +disabled logging && logfile=/dev/null + +# command line configuration sanity checks + +# we need to build at least one lib type +if ! enabled_any static shared; then + cat < $logfile +set >> $logfile + +test -n "$valgrind" && toolchain="valgrind-memcheck" + +enabled ossfuzz && ! echo $CFLAGS | grep -q -- "-fsanitize=" && ! echo $CFLAGS | grep -q -- "-fcoverage-mapping" &&{ + add_cflags -fsanitize=address,undefined -fsanitize-coverage=trace-pc-guard,trace-cmp -fno-omit-frame-pointer + add_ldflags -fsanitize=address,undefined -fsanitize-coverage=trace-pc-guard,trace-cmp +} + +case "$toolchain" in + *-asan) + cc_default="${toolchain%-asan}" + add_cflags -fsanitize=address + add_ldflags -fsanitize=address + ;; + *-msan) + cc_default="${toolchain%-msan}" + add_cflags -fsanitize=memory -fsanitize-memory-track-origins + add_ldflags -fsanitize=memory + ;; + *-tsan) + cc_default="${toolchain%-tsan}" + add_cflags -fsanitize=thread + add_ldflags -fsanitize=thread + case "$toolchain" in + gcc-tsan) + add_cflags -fPIC + add_ldflags -fPIC + ;; + esac + ;; + *-usan) + cc_default="${toolchain%-usan}" + add_cflags -fsanitize=undefined + add_ldflags -fsanitize=undefined + ;; + valgrind-*) + target_exec_default="valgrind" + case "$toolchain" in + valgrind-massif) + target_exec_args="--tool=massif --alloc-fn=av_malloc --alloc-fn=av_mallocz --alloc-fn=av_calloc --alloc-fn=av_fast_padded_malloc --alloc-fn=av_fast_malloc --alloc-fn=av_realloc_f --alloc-fn=av_fast_realloc --alloc-fn=av_realloc" + ;; + valgrind-memcheck) + target_exec_args="--error-exitcode=1 --malloc-fill=0x2a --track-origins=yes --leak-check=full --gen-suppressions=all --suppressions=$source_path/tests/fate-valgrind.supp" + ;; + esac + ;; + msvc) + # Check whether the current MSVC version needs the C99 converter. + # From MSVC 2013 (compiler major version 18) onwards, it does actually + # support enough of C99 to build ffmpeg. Default to the new + # behaviour if the regexp was unable to match anything, since this + # successfully parses the version number of existing supported + # versions that require the converter (MSVC 2010 and 2012). + cl_major_ver=$(cl.exe 2>&1 | sed -n 's/.*Version \([[:digit:]]\{1,\}\)\..*/\1/p') + if [ -z "$cl_major_ver" ] || [ $cl_major_ver -ge 18 ]; then + cc_default="cl.exe" + cxx_default="cl.exe" + else + die "Unsupported MSVC version (2013 or newer required)" + fi + ld_default="$source_path/compat/windows/mslink" + nm_default="dumpbin.exe -symbols" + ar_default="lib.exe" + case "$arch" in + aarch64|arm64) + as_default="armasm64.exe" + ;; + arm*) + as_default="armasm.exe" + ;; + esac + target_os_default="win32" + # Use a relative path for TMPDIR. This makes sure all the + # ffconf temp files are written with a relative path, avoiding + # issues with msys/win32 path conversion for MSVC parameters + # such as -Fo or -out:. + TMPDIR=. + ;; + icl) + cc_default="icl" + ld_default="xilink" + nm_default="dumpbin -symbols" + ar_default="xilib" + target_os_default="win32" + TMPDIR=. + ;; + gcov) + add_cflags -fprofile-arcs -ftest-coverage + add_ldflags -fprofile-arcs -ftest-coverage + ;; + llvm-cov) + add_cflags -fprofile-arcs -ftest-coverage + add_ldflags --coverage + ;; + hardened) + add_cppflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 + add_cflags -fno-strict-overflow -fstack-protector-all + add_ldflags -Wl,-z,relro -Wl,-z,now + add_cflags -fPIE + add_ldexeflags -fPIE -pie + ;; + ?*) + die "Unknown toolchain $toolchain" + ;; +esac + +if test -n "$cross_prefix"; then + test -n "$arch" && test -n "$target_os" || + die "Must specify target arch (--arch) and OS (--target-os) when cross-compiling" + enable cross_compile +fi + +set_default target_os +if test "$target_os" = android; then + cc_default="clang" +fi + +ar_default="${cross_prefix}${ar_default}" +cc_default="${cross_prefix}${cc_default}" +cxx_default="${cross_prefix}${cxx_default}" +nm_default="${cross_prefix}${nm_default}" +pkg_config_default="${cross_prefix}${pkg_config_default}" +if ${cross_prefix}${ranlib_default} 2>&1 | grep -q "\-D "; then + ranlib_default="${cross_prefix}${ranlib_default} -D" +else + ranlib_default="${cross_prefix}${ranlib_default}" +fi +strip_default="${cross_prefix}${strip_default}" +windres_default="${cross_prefix}${windres_default}" + +sysinclude_default="${sysroot}/usr/include" + +if enabled cuda_sdk; then + warn "Option --enable-cuda-sdk is deprecated. Use --enable-cuda-nvcc instead." + enable cuda_nvcc +fi + +if enabled cuda_nvcc; then + nvcc_default="nvcc" + nvccflags_default="-gencode arch=compute_30,code=sm_30 -O2" +else + nvcc_default="clang" + nvccflags_default="--cuda-gpu-arch=sm_30 -O2" + NVCC_C="" +fi + +set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ + target_exec x86asmexe nvcc +enabled cross_compile || host_cc_default=$cc +set_default host_cc + +pkg_config_fail_message="" +if ! $pkg_config --version >/dev/null 2>&1; then + warn "$pkg_config not found, library detection may fail." + pkg_config=false +elif is_in -static $cc $LDFLAGS && ! is_in --static $pkg_config $pkg_config_flags; then + pkg_config_fail_message=" +Note: When building a static binary, add --pkg-config-flags=\"--static\"." +fi + +if test $doxygen != $doxygen_default && \ + ! $doxygen --version >/dev/null 2>&1; then + warn "Specified doxygen \"$doxygen\" not found, API documentation will fail to build." +fi + +exesuf() { + case $1 in + mingw32*|mingw64*|win32|win64|cygwin*|*-dos|freedos|opendos|os/2*|symbian) echo .exe ;; + esac +} + +EXESUF=$(exesuf $target_os) +HOSTEXESUF=$(exesuf $host_os) + +# set temporary file name +: ${TMPDIR:=$TEMPDIR} +: ${TMPDIR:=$TMP} +: ${TMPDIR:=/tmp} + +if [ -n "$tempprefix" ] ; then + mktemp(){ + tmpname="$tempprefix.${HOSTNAME}.${UID}" + echo "$tmpname" + mkdir "$tmpname" + } +elif ! test_cmd mktemp -u XXXXXX; then + # simple replacement for missing mktemp + # NOT SAFE FOR GENERAL USE + mktemp(){ + tmpname="${2%%XXX*}.${HOSTNAME}.${UID}.$$" + echo "$tmpname" + mkdir "$tmpname" + } +fi + +FFTMPDIR=$(mktemp -d "${TMPDIR}/ffconf.XXXXXXXX" 2> /dev/null) || + die "Unable to create temporary directory in $TMPDIR." + +tmpfile(){ + tmp="${FFTMPDIR}/test"$2 + (set -C; exec > $tmp) 2> /dev/null || + die "Unable to create temporary file in $FFTMPDIR." + eval $1=$tmp +} + +trap 'rm -rf -- "$FFTMPDIR"' EXIT +trap 'exit 2' INT + +tmpfile TMPASM .asm +tmpfile TMPC .c +tmpfile TMPCPP .cpp +tmpfile TMPE $EXESUF +tmpfile TMPH .h +tmpfile TMPM .m +tmpfile TMPCU .cu +tmpfile TMPO .o +tmpfile TMPS .S +tmpfile TMPSH .sh +tmpfile TMPV .ver + +unset -f mktemp + +chmod +x $TMPE + +# make sure we can execute files in $TMPDIR +cat > $TMPSH 2>> $logfile <> $logfile 2>&1 +if ! $TMPSH >> $logfile 2>&1; then + cat <&1 | grep -q '^GNU assembler'; then + true # no-op to avoid reading stdin in following checks + elif $_cc -v 2>&1 | grep -q '^gcc.*LLVM'; then + _type=llvm_gcc + gcc_extra_ver=$(expr "$($_cc --version 2>/dev/null | head -n1)" : '.*\((.*)\)') + _ident="llvm-gcc $($_cc -dumpversion 2>/dev/null) $gcc_extra_ver" + _depflags='-MMD -MF $(@:.o=.d) -MT $@' +# _cflags_speed='-O3' + _cflags_size='-Os' + elif $_cc -v 2>&1 | grep -qi ^gcc; then + _type=gcc + gcc_version=$($_cc --version | head -n1) + gcc_basever=$($_cc -dumpversion) + gcc_pkg_ver=$(expr "$gcc_version" : '[^ ]* \(([^)]*)\)') + gcc_ext_ver=$(expr "$gcc_version" : ".*$gcc_pkg_ver $gcc_basever \\(.*\\)") + _ident=$(cleanws "gcc $gcc_basever $gcc_pkg_ver $gcc_ext_ver") + case $gcc_basever in + 2) ;; + 2.*) ;; + *) _depflags='-MMD -MF $(@:.o=.d) -MT $@' ;; + esac + if [ "$first" = true ]; then + case $gcc_basever in + 4.2*) + warn "gcc 4.2 is outdated and may miscompile FFmpeg. Please use a newer compiler." ;; + esac + fi +# _cflags_speed='-O3' + _cflags_size='-Os' + elif $_cc --version 2>/dev/null | grep -q ^icc; then + _type=icc + _ident=$($_cc --version | head -n1) + _depflags='-MMD' +# _cflags_speed='-O3' + _cflags_size='-Os' + _cflags_noopt='-O1' + _flags_filter=icc_flags + elif $_cc -v 2>&1 | grep -q xlc; then + _type=xlc + _ident=$($_cc -qversion 2>/dev/null | head -n1) +# _cflags_speed='-O5' + _cflags_size='-O5 -qcompact' + elif $_cc --vsn 2>/dev/null | grep -Eq "ARM (C/C\+\+ )?Compiler"; then + test -d "$sysroot" || die "No valid sysroot specified." + _type=armcc + _ident=$($_cc --vsn | grep -i build | head -n1 | sed 's/.*: //') + armcc_conf="$PWD/armcc.conf" + $_cc --arm_linux_configure \ + --arm_linux_config_file="$armcc_conf" \ + --configure_sysroot="$sysroot" \ + --configure_cpp_headers="$sysinclude" >>$logfile 2>&1 || + die "Error creating armcc configuration file." + $_cc --vsn | grep -q RVCT && armcc_opt=rvct || armcc_opt=armcc + _flags="--arm_linux_config_file=$armcc_conf --translate_gcc" + as_default="${cross_prefix}gcc" + _depflags='-MMD' +# _cflags_speed='-O3' + _cflags_size='-Os' + elif $_cc -v 2>&1 | grep -q clang && ! $_cc -? > /dev/null 2>&1; then + _type=clang + _ident=$($_cc --version 2>/dev/null | head -n1) + _depflags='-MMD -MF $(@:.o=.d) -MT $@' +# _cflags_speed='-O3' + _cflags_size='-Oz' + elif $_cc -V 2>&1 | grep -q Sun; then + _type=suncc + _ident=$($_cc -V 2>&1 | head -n1 | cut -d' ' -f 2-) + _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< | sed -e "1s,^.*: ,$@: ," -e "\$$!s,\$$, \\\," -e "1!s,^.*: , ," > $(@:.o=.d)' + _DEPFLAGS='-xM1 -xc99' + _ldflags='-std=c99' +# _cflags_speed='-O5' + _cflags_size='-O5 -xspace' + _flags_filter=suncc_flags + elif $_cc -v 2>&1 | grep -q 'PathScale\|Path64'; then + _type=pathscale + _ident=$($_cc -v 2>&1 | head -n1 | tr -d :) + _depflags='-MMD -MF $(@:.o=.d) -MT $@' +# _cflags_speed='-O2' + _cflags_size='-Os' + _flags_filter='filter_out -Wdisabled-optimization' + elif $_cc -v 2>&1 | grep -q Open64; then + _type=open64 + _ident=$($_cc -v 2>&1 | head -n1 | tr -d :) + _depflags='-MMD -MF $(@:.o=.d) -MT $@' +# _cflags_speed='-O2' + _cflags_size='-Os' + _flags_filter='filter_out -Wdisabled-optimization|-Wtype-limits|-fno-signed-zeros' + elif $_cc 2>&1 | grep -q 'Microsoft.*ARM.*Assembler'; then + _type=armasm + _ident=$($_cc | head -n1) + # 4509: "This form of conditional instruction is deprecated" + _flags="-nologo -ignore 4509" + _flags_filter=armasm_flags + elif $_cc 2>&1 | grep -q Intel; then + _type=icl + _ident=$($_cc 2>&1 | head -n1) + _depflags='-QMMD -QMF$(@:.o=.d) -QMT$@' + # Not only is O3 broken on 13.x+ but it is slower on all previous + # versions (tested) as well. +# _cflags_speed="-O2" + _cflags_size="-O1 -Oi" # -O1 without -Oi miscompiles stuff + if $_cc 2>&1 | grep -q Linker; then + _ld_o='-out:$@' + else + _ld_o='-Fe$@' + fi + _cc_o='-Fo$@' + _cc_e='-P' + _flags_filter=icl_flags + _ld_lib='lib%.a' + _ld_path='-libpath:' + # -Qdiag-error to make icl error when seeing certain unknown arguments + _flags='-nologo -Qdiag-error:4044,10157' + # -Qvec- -Qsimd- to prevent miscompilation, -GS, fp:precise for consistency + # with MSVC which enables it by default. + _cflags='-Qms0 -Qvec- -Qsimd- -GS -fp:precise' + disable stripping + elif $_cc -? 2>/dev/null | grep -q 'LLVM.*Linker'; then + # lld can emulate multiple different linkers; in ms link.exe mode, + # the -? parameter gives the help output which contains an identifyable + # string, while it gives an error in other modes. + _type=lld-link + # The link.exe mode doesn't have a switch for getting the version, + # but we can force it back to gnu mode and get the version from there. + _ident=$($_cc -flavor gnu --version 2>/dev/null) + _ld_o='-out:$@' + _flags_filter=msvc_flags + _ld_lib='lib%.a' + _ld_path='-libpath:' + elif $_cc -nologo- 2>&1 | grep -q Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then + _type=msvc + _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') + _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' + _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs' +# _cflags_speed="-O2" + _cflags_size="-O1" + _cflags_noopt="-O1" + if $_cc -nologo- 2>&1 | grep -q Linker; then + _ld_o='-out:$@' + else + _ld_o='-Fe$@' + fi + _cc_o='-Fo$@' + _cc_e='-P -Fi$@' + _flags_filter=msvc_flags + _ld_lib='lib%.a' + _ld_path='-libpath:' + _flags='-nologo' + disable stripping + elif $_cc --version 2>/dev/null | grep -q ^cparser; then + _type=cparser + _ident=$($_cc --version | head -n1) + _depflags='-MMD' +# _cflags_speed='-O4' + _cflags_size='-O2' + _flags_filter=cparser_flags + fi + + # Debug: + #_cflags_speed='-O0' + #_cflags_size='-O0' + + eval ${pfx}_type=\$_type + eval ${pfx}_ident=\$_ident +} + +set_ccvars(){ + eval ${1}_C=\${_cc_c-\${${1}_C}} + eval ${1}_E=\${_cc_e-\${${1}_E}} + eval ${1}_O=\${_cc_o-\${${1}_O}} + + if [ -n "$_depflags" ]; then + eval ${1}_DEPFLAGS=\$_depflags + else + eval ${1}DEP=\${_DEPCMD:-\$DEPCMD} + eval ${1}DEP_FLAGS=\${_DEPFLAGS:-\$DEPFLAGS} + eval DEP${1}FLAGS=\$_flags + fi +} + +probe_cc cc "$cc" "true" +cflags_filter=$_flags_filter +cflags_speed=$_cflags_speed +cflags_size=$_cflags_size +cflags_noopt=$_cflags_noopt +add_cflags $_flags $_cflags +cc_ldflags=$_ldflags +set_ccvars CC +set_ccvars CXX + +echo "cflags_filter: $cflags_filter" +echo "cflags_speed: $cflags_speed" +echo "cflags_size: $cflags_size" +echo "cflags_noopt: $cflags_noopt" +echo "_flags: $_flags" +echo "cc_ldflags: $_ldflags" + + +probe_cc hostcc "$host_cc" +host_cflags_filter=$_flags_filter +host_cflags_speed=$_cflags_speed +add_host_cflags $_flags $_cflags +set_ccvars HOSTCC + +test -n "$cc_type" && enable $cc_type || + warn "Unknown C compiler $cc, unable to select optimal CFLAGS" + +: ${as_default:=$cc} +: ${objcc_default:=$cc} +: ${dep_cc_default:=$cc} +: ${ld_default:=$cc} +: ${host_ld_default:=$host_cc} +set_default ar as objcc dep_cc ld ln_s host_ld windres + +probe_cc as "$as" +asflags_filter=$_flags_filter +add_asflags $_flags $_cflags +set_ccvars AS + +probe_cc objcc "$objcc" +objcflags_filter=$_flags_filter +add_objcflags $_flags $_cflags +set_ccvars OBJC + +probe_cc ld "$ld" +ldflags_filter=$_flags_filter +add_ldflags $_flags $_ldflags +test "$cc_type" != "$ld_type" && add_ldflags $cc_ldflags +LD_O=${_ld_o-$LD_O} +LD_LIB=${_ld_lib-$LD_LIB} +LD_PATH=${_ld_path-$LD_PATH} + +probe_cc hostld "$host_ld" +host_ldflags_filter=$_flags_filter +add_host_ldflags $_flags $_ldflags +HOSTLD_O=${_ld_o-$HOSTLD_O} + +if [ -z "$CC_DEPFLAGS" ] && [ "$dep_cc" != "$cc" ]; then + probe_cc depcc "$dep_cc" + CCDEP=${_DEPCMD:-$DEPCMD} + CCDEP_FLAGS=${_DEPFLAGS:=$DEPFLAGS} + DEPCCFLAGS=$_flags +fi + +if $ar 2>&1 | grep -q Microsoft; then + arflags="-nologo" + ar_o='-out:$@' +elif $ar 2>&1 | grep -q "\[D\] "; then + arflags="rcD" + ar_o='$@' +else + arflags="rc" + ar_o='$@' +fi + +add_cflags $extra_cflags +add_cxxflags $extra_cxxflags +add_objcflags $extra_objcflags +add_asflags $extra_cflags + +if test -n "$sysroot"; then + case "$cc_type" in + gcc|llvm_gcc|clang) + add_cppflags --sysroot="$sysroot" + add_ldflags --sysroot="$sysroot" + ;; + esac +fi + +if test "$cpu" = host; then + enabled cross_compile && + die "--cpu=host makes no sense when cross-compiling." + + case "$cc_type" in + gcc|llvm_gcc) + check_native(){ + $cc $1=native -v -c -o $TMPO $TMPC >$TMPE 2>&1 || return + sed -n "/cc1.*$1=/{ + s/.*$1=\\([^ ]*\\).*/\\1/ + p + q + }" $TMPE + } + cpu=$(check_native -march || check_native -mcpu) + ;; + clang) + check_native(){ + $cc $1=native -v -c -o $TMPO $TMPC >$TMPE 2>&1 || return + sed -n "/cc1.*-target-cpu /{ + s/.*-target-cpu \\([^ ]*\\).*/\\1/ + p + q + }" $TMPE + } + cpu=$(check_native -march) + ;; + esac + + test "${cpu:-host}" = host && + die "--cpu=host not supported with compiler $cc" +fi + +# Deal with common $arch aliases +case "$arch" in + aarch64|arm64) + arch="aarch64" + ;; + arm*|iPad*|iPhone*) + arch="arm" + ;; + mips*|IP*) + case "$arch" in + *el) + add_cppflags -EL + add_ldflags -EL + ;; + *eb) + add_cppflags -EB + add_ldflags -EB + ;; + esac + arch="mips" + ;; + parisc*|hppa*) + arch="parisc" + ;; + "Power Macintosh"|ppc*|powerpc*) + arch="ppc" + ;; + s390|s390x) + arch="s390" + ;; + sh4|sh) + arch="sh4" + ;; + sun4*|sparc*) + arch="sparc" + ;; + tilegx|tile-gx) + arch="tilegx" + ;; + i[3-6]86*|i86pc|BePC|x86pc|x86_64|x86_32|amd64) + arch="x86" + ;; +esac + +is_in $arch $ARCH_LIST || warn "unknown architecture $arch" +enable $arch + +# Add processor-specific flags +if enabled aarch64; then + + case $cpu in + armv*) + cpuflags="-march=$cpu" + ;; + *) + cpuflags="-mcpu=$cpu" + ;; + esac + +elif enabled alpha; then + + cpuflags="-mcpu=$cpu" + +elif enabled arm; then + + check_arm_arch() { + test_cpp_condition stddef.h \ + "defined __ARM_ARCH_${1}__ || defined __TARGET_ARCH_${2:-$1}" \ + $cpuflags + } + + probe_arm_arch() { + if check_arm_arch 4; then echo armv4 + elif check_arm_arch 4T; then echo armv4t + elif check_arm_arch 5; then echo armv5 + elif check_arm_arch 5E; then echo armv5e + elif check_arm_arch 5T; then echo armv5t + elif check_arm_arch 5TE; then echo armv5te + elif check_arm_arch 5TEJ; then echo armv5te + elif check_arm_arch 6; then echo armv6 + elif check_arm_arch 6J; then echo armv6j + elif check_arm_arch 6K; then echo armv6k + elif check_arm_arch 6Z; then echo armv6z + elif check_arm_arch 6KZ; then echo armv6zk + elif check_arm_arch 6ZK; then echo armv6zk + elif check_arm_arch 6T2; then echo armv6t2 + elif check_arm_arch 7; then echo armv7 + elif check_arm_arch 7A 7_A; then echo armv7-a + elif check_arm_arch 7S; then echo armv7-a + elif check_arm_arch 7R 7_R; then echo armv7-r + elif check_arm_arch 7M 7_M; then echo armv7-m + elif check_arm_arch 7EM 7E_M; then echo armv7-m + elif check_arm_arch 8A 8_A; then echo armv8-a + fi + } + + [ "$cpu" = generic ] && cpu=$(probe_arm_arch) + + case $cpu in + armv*) + cpuflags="-march=$cpu" + subarch=$(echo $cpu | sed 's/[^a-z0-9]//g') + ;; + *) + cpuflags="-mcpu=$cpu" + case $cpu in + cortex-a*) subarch=armv7a ;; + cortex-r*) subarch=armv7r ;; + cortex-m*) enable thumb; subarch=armv7m ;; + arm11*) subarch=armv6 ;; + arm[79]*e*|arm9[24]6*|arm96*|arm102[26]) subarch=armv5te ;; + armv4*|arm7*|arm9[24]*) subarch=armv4 ;; + *) subarch=$(probe_arm_arch) ;; + esac + ;; + esac + + case "$subarch" in + armv5t*) enable fast_clz ;; + armv[6-8]*) + enable fast_clz + disabled fast_unaligned || enable fast_unaligned + ;; + esac + +elif enabled avr32; then + + case $cpu in + ap7[02]0[0-2]) + subarch="avr32_ap" + cpuflags="-mpart=$cpu" + ;; + ap) + subarch="avr32_ap" + cpuflags="-march=$cpu" + ;; + uc3[ab]*) + subarch="avr32_uc" + cpuflags="-mcpu=$cpu" + ;; + uc) + subarch="avr32_uc" + cpuflags="-march=$cpu" + ;; + esac + +elif enabled bfin; then + + cpuflags="-mcpu=$cpu" + +elif enabled mips; then + + cpuflags="-march=$cpu" + + if [ "$cpu" != "generic" ]; then + disable mips32r2 + disable mips32r5 + disable mips64r2 + disable mips32r6 + disable mips64r6 + disable loongson2 + disable loongson3 + + case $cpu in + 24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf) + enable mips32r2 + disable msa + ;; + p5600|i6400|p6600) + disable mipsdsp + disable mipsdspr2 + ;; + loongson*) + enable loongson2 + enable loongson3 + enable local_aligned + enable simd_align_16 + enable fast_64bit + enable fast_clz + enable fast_cmov + enable fast_unaligned + disable aligned_stack + disable mipsdsp + disable mipsdspr2 + # When gcc version less than 5.3.0, add -fno-expensive-optimizations flag. + if [ $cc == gcc ]; then + gcc_version=$(gcc -dumpversion) + if [ "$(echo "$gcc_version 5.3.0" | tr " " "\n" | sort -rV | head -n 1)" == "$gcc_version" ]; then + expensive_optimization_flag="" + else + expensive_optimization_flag="-fno-expensive-optimizations" + fi + fi + case $cpu in + loongson3*) + cpuflags="-march=loongson3a -mhard-float $expensive_optimization_flag" + ;; + loongson2e) + cpuflags="-march=loongson2e -mhard-float $expensive_optimization_flag" + ;; + loongson2f) + cpuflags="-march=loongson2f -mhard-float $expensive_optimization_flag" + ;; + esac + ;; + *) + # Unknown CPU. Disable everything. + warn "unknown CPU. Disabling all MIPS optimizations." + disable mipsfpu + disable mipsdsp + disable mipsdspr2 + disable msa + disable mmi + ;; + esac + + case $cpu in + 24kc) + disable mipsfpu + disable mipsdsp + disable mipsdspr2 + ;; + 24kf*) + disable mipsdsp + disable mipsdspr2 + ;; + 24kec|34kc|1004kc) + disable mipsfpu + disable mipsdspr2 + ;; + 24kef*|34kf*|1004kf*) + disable mipsdspr2 + ;; + 74kc) + disable mipsfpu + ;; + p5600) + enable mips32r5 + check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" + ;; + i6400) + enable mips64r6 + check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + p6600) + enable mips64r6 + check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + esac + else + # We do not disable anything. Is up to the user to disable the unwanted features. + warn 'generic cpu selected' + fi + +elif enabled ppc; then + + disable ldbrx + + case $(tolower $cpu) in + 601|ppc601|powerpc601) + cpuflags="-mcpu=601" + disable altivec + ;; + 603*|ppc603*|powerpc603*) + cpuflags="-mcpu=603" + disable altivec + ;; + 604*|ppc604*|powerpc604*) + cpuflags="-mcpu=604" + disable altivec + ;; + g3|75*|ppc75*|powerpc75*) + cpuflags="-mcpu=750" + disable altivec + ;; + g4|745*|ppc745*|powerpc745*) + cpuflags="-mcpu=7450" + disable vsx + ;; + 74*|ppc74*|powerpc74*) + cpuflags="-mcpu=7400" + disable vsx + ;; + g5|970|ppc970|powerpc970) + cpuflags="-mcpu=970" + disable vsx + ;; + power[3-6]*) + cpuflags="-mcpu=$cpu" + disable vsx + ;; + power[7-8]*) + cpuflags="-mcpu=$cpu" + ;; + cell) + cpuflags="-mcpu=cell" + enable ldbrx + disable vsx + ;; + e500mc) + cpuflags="-mcpu=e500mc" + disable altivec + ;; + e500v2) + cpuflags="-mcpu=8548 -mhard-float -mfloat-gprs=double" + disable altivec + disable dcbzl + ;; + e500) + cpuflags="-mcpu=8540 -mhard-float" + disable altivec + disable dcbzl + ;; + esac + +elif enabled sparc; then + + case $cpu in + cypress|f93[04]|tsc701|sparcl*|supersparc|hypersparc|niagara|v[789]) + cpuflags="-mcpu=$cpu" + ;; + ultrasparc*|niagara[234]) + cpuflags="-mcpu=$cpu" + ;; + esac + +elif enabled x86; then + + case $cpu in + i[345]86|pentium) + cpuflags="-march=$cpu" + disable i686 + disable mmx + ;; + # targets that do NOT support nopl and conditional mov (cmov) + pentium-mmx|k6|k6-[23]|winchip-c6|winchip2|c3) + cpuflags="-march=$cpu" + disable i686 + ;; + # targets that do support nopl and conditional mov (cmov) + i686|pentiumpro|pentium[23]|pentium-m|athlon|athlon-tbird|athlon-4|athlon-[mx]p|athlon64*|k8*|opteron*|athlon-fx\ + |core*|atom|bonnell|nehalem|westmere|silvermont|sandybridge|ivybridge|haswell|broadwell|skylake*|knl\ + |amdfam10|barcelona|b[dt]ver*|znver*) + cpuflags="-march=$cpu" + enable i686 + enable fast_cmov + ;; + # targets that do support conditional mov but on which it's slow + pentium4|pentium4m|prescott|nocona) + cpuflags="-march=$cpu" + enable i686 + disable fast_cmov + ;; + esac + +fi + +if [ "$cpu" != generic ]; then + add_cflags $cpuflags + add_asflags $cpuflags + test "$cc_type" = "$ld_type" && add_ldflags $cpuflags +fi + +# compiler sanity check +test_exec <= 201112L" && + add_cflags -std=c11 || + check_cflags -std=c99 + +check_cppflags -D_FILE_OFFSET_BITS=64 +check_cppflags -D_LARGEFILE_SOURCE + +add_host_cppflags -D_ISOC99_SOURCE +check_host_cflags -std=c99 +check_host_cflags -Wall +check_host_cflags $host_cflags_speed + +check_64bit(){ + arch32=$1 + arch64=$2 + expr=${3:-'sizeof(void *) > 4'} + test_code cc "" "int test[2*($expr) - 1]" && + subarch=$arch64 || subarch=$arch32 + enable $subarch +} + +case "$arch" in + aarch64|alpha|ia64) + enabled shared && enable_weak pic + ;; + mips) + check_64bit mips mips64 '_MIPS_SIM > 1' + enabled shared && enable_weak pic + ;; + parisc) + check_64bit parisc parisc64 + enabled shared && enable_weak pic + ;; + ppc) + check_64bit ppc ppc64 + enabled shared && enable_weak pic + ;; + s390) + check_64bit s390 s390x + enabled shared && enable_weak pic + ;; + sparc) + check_64bit sparc sparc64 + enabled shared && enable_weak pic + ;; + x86) + check_64bit x86_32 x86_64 + # Treat x32 as x64 for now. Note it also needs pic if shared + test "$subarch" = "x86_32" && test_cpp_condition stddef.h 'defined(__x86_64__)' && + subarch=x86_64 && enable x86_64 && disable x86_32 + if enabled x86_64; then + enabled shared && enable_weak pic + objformat=elf64 + fi + ;; +esac + +# OS specific +case $target_os in + aix) + SHFLAGS=-shared + add_cppflags '-I\$(SRC_PATH)/compat/aix' + enabled shared && add_ldflags -Wl,-brtl + arflags='-Xany -r -c' + striptype="" + ;; + android) + disable symver + enable section_data_rel_ro + add_cflags -fPIE + add_ldexeflags -fPIE -pie + SLIB_INSTALL_NAME='$(SLIBNAME)' + SLIB_INSTALL_LINKS= + SHFLAGS='-shared -Wl,-soname,$(SLIBNAME)' + ;; + haiku) + prefix_default="/boot/common" + network_extralibs="-lnetwork" + host_extralibs= + ;; + sunos) + SHFLAGS='-shared -Wl,-h,$$(@F)' + enabled x86 && append SHFLAGS -mimpure-text + network_extralibs="-lsocket -lnsl" + add_cppflags -D__EXTENSIONS__ + # When using suncc to build, the Solaris linker will mark + # an executable with each instruction set encountered by + # the Solaris assembler. As our libraries contain their own + # guards for processor-specific code, instead suppress + # generation of the HWCAPS ELF section on Solaris x86 only. + enabled_all suncc x86 && + echo "hwcap_1 = OVERRIDE;" > mapfile && + add_ldflags -Wl,-M,mapfile + nm_default='nm -P -g' + striptype="" + version_script='-M' + VERSION_SCRIPT_POSTPROCESS_CMD='perl $(SRC_PATH)/compat/solaris/make_sunver.pl - $(OBJS)' + ;; + netbsd) + disable symver + oss_indev_extralibs="-lossaudio" + oss_outdev_extralibs="-lossaudio" + enabled gcc || check_ldflags -Wl,-zmuldefs + ;; + openbsd|bitrig) + disable symver + striptype="" + SHFLAGS='-shared' + SLIB_INSTALL_NAME='$(SLIBNAME).$(LIBMAJOR).$(LIBMINOR)' + SLIB_INSTALL_LINKS= + oss_indev_extralibs="-lossaudio" + oss_outdev_extralibs="-lossaudio" + ;; + dragonfly) + disable symver + ;; + freebsd) + ;; + bsd/os) + add_extralibs -lpoll -lgnugetopt + strip="strip -d" + ;; + darwin) + enabled ppc && add_asflags -force_cpusubtype_ALL + install_name_dir_default='$(SHLIBDIR)' + SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(INSTALL_NAME_DIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)' + enabled x86_32 && append SHFLAGS -Wl,-read_only_relocs,suppress + strip="${strip} -x" + add_ldflags -Wl,-dynamic,-search_paths_first + check_cflags -Werror=partial-availability + SLIBSUF=".dylib" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME).$(LIBVERSION)$(SLIBSUF)' + SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME).$(LIBMAJOR)$(SLIBSUF)' + enabled x86_64 && objformat="macho64" || objformat="macho32" + enabled_any pic shared x86_64 || + { check_cflags -mdynamic-no-pic && add_asflags -mdynamic-no-pic; } + check_headers dispatch/dispatch.h && + add_cppflags '-I\$(SRC_PATH)/compat/dispatch_semaphore' + if test -n "$sysroot"; then + is_in -isysroot $cc $CPPFLAGS $CFLAGS || check_cppflags -isysroot $sysroot + is_in -isysroot $ld $LDFLAGS || check_ldflags -isysroot $sysroot + fi + version_script='-exported_symbols_list' + VERSION_SCRIPT_POSTPROCESS_CMD='tr " " "\n" | sed -n /global:/,/local:/p | grep ";" | tr ";" "\n" | sed -E "s/(.+)/_\1/g" | sed -E "s/(.+[^*])$$$$/\1*/"' + ;; + msys*) + die "Native MSYS builds are discouraged, please use the MINGW environment." + ;; + mingw32*|mingw64*) + target_os=mingw32 + LIBTARGET=i386 + if enabled x86_64; then + LIBTARGET="i386:x86-64" + elif enabled arm; then + LIBTARGET="arm" + elif enabled aarch64; then + LIBTARGET="arm64" + fi + if enabled shared; then + # Cannot build both shared and static libs when using dllimport. + disable static + fi + enabled shared && ! enabled small && test_cmd $windres --version && enable gnu_windres + enabled x86_32 && check_ldflags -Wl,--large-address-aware + shlibdir_default="$bindir_default" + SLIBPREF="" + SLIBSUF=".dll" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' + SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' + if test_cmd lib.exe -list; then + SLIB_EXTRA_CMD=-'lib.exe -nologo -machine:$(LIBTARGET) -def:$$(@:$(SLIBSUF)=.def) -out:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' + if enabled x86_64; then + LIBTARGET=x64 + fi + else + SLIB_EXTRA_CMD=-'$(DLLTOOL) -m $(LIBTARGET) -d $$(@:$(SLIBSUF)=.def) -l $(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib) -D $(SLIBNAME_WITH_MAJOR)' + fi + SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' + SLIB_INSTALL_LINKS= + SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' + SLIB_INSTALL_EXTRA_LIB='lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' + SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" AR="$(AR_CMD)" NM="$(NM_CMD)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' + SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--disable-auto-image-base $$(@:$(SLIBSUF)=.def)' + enabled x86_64 && objformat="win64" || objformat="win32" + dlltool="${cross_prefix}dlltool" + ranlib=: + enable dos_paths + check_ldflags -Wl,--nxcompat,--dynamicbase + # Lets work around some stupidity in binutils. + # ld will strip relocations from executables even though we need them + # for dynamicbase (ASLR). Using -pie does retain the reloc section + # however ld then forgets what the entry point should be (oops) so we + # have to manually (re)set it. + if enabled x86_32; then + disabled debug && add_ldexeflags -Wl,--pic-executable,-e,_mainCRTStartup + elif enabled x86_64; then + disabled debug && add_ldexeflags -Wl,--pic-executable,-e,mainCRTStartup + check_ldflags -Wl,--high-entropy-va # binutils 2.25 + # Set image base >4GB for extra entropy with HEASLR + add_ldexeflags -Wl,--image-base,0x140000000 + append SHFLAGS -Wl,--image-base,0x180000000 + fi + ;; + win32|win64) + disable symver + if enabled shared; then + # Link to the import library instead of the normal static library + # for shared libs. + LD_LIB='%.lib' + # Cannot build both shared and static libs with MSVC or icl. + disable static + fi + enabled x86_32 && check_ldflags -LARGEADDRESSAWARE + shlibdir_default="$bindir_default" + SLIBPREF="" + SLIBSUF=".dll" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' + SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' + SLIB_CREATE_DEF_CMD='EXTERN_PREFIX="$(EXTERN_PREFIX)" $(SRC_PATH)/compat/windows/makedef $(SUBDIR)lib$(NAME).ver $(OBJS) > $$(@:$(SLIBSUF)=.def)' + SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' + SLIB_INSTALL_LINKS= + SLIB_INSTALL_EXTRA_SHLIB='$(SLIBNAME:$(SLIBSUF)=.lib)' + SLIB_INSTALL_EXTRA_LIB='$(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)' + SHFLAGS='-dll -def:$$(@:$(SLIBSUF)=.def) -implib:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)' + enabled x86_64 && objformat="win64" || objformat="win32" + ranlib=: + enable dos_paths + ;; + cygwin*) + target_os=cygwin + shlibdir_default="$bindir_default" + SLIBPREF="cyg" + SLIBSUF=".dll" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' + SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' + SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' + SLIB_INSTALL_LINKS= + SLIB_INSTALL_EXTRA_LIB='lib$(FULLNAME).dll.a' + SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(FULLNAME).dll.a' + enabled x86_64 && objformat="win64" || objformat="win32" + enable dos_paths + enabled shared && ! enabled small && test_cmd $windres --version && enable gnu_windres + add_cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 + ;; + *-dos|freedos|opendos) + network_extralibs="-lsocket" + objformat="coff" + enable dos_paths + ;; + linux) + enable section_data_rel_ro + enabled_any arm aarch64 && enable_weak linux_perf + ;; + irix*) + target_os=irix + ranlib="echo ignoring ranlib" + ;; + os/2*) + strip="lxlite -CS" + striptype="" + objformat="aout" + add_cppflags -D_GNU_SOURCE + add_ldflags -Zomf -Zbin-files -Zargs-wild -Zhigh-mem -Zmap + SHFLAGS='$(SUBDIR)$(NAME).def -Zdll -Zomf' + LIBSUF="_s.a" + SLIBPREF="" + SLIBSUF=".dll" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' + SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(shell echo $(FULLNAME) | cut -c1-6)$(LIBMAJOR)$(SLIBSUF)' + SLIB_CREATE_DEF_CMD='echo LIBRARY $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=) INITINSTANCE TERMINSTANCE > $(SUBDIR)$(FULLNAME).def; \ + echo CODE PRELOAD MOVEABLE DISCARDABLE >> $(SUBDIR)$(FULLNAME).def; \ + echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $(SUBDIR)$(FULLNAME).def; \ + echo EXPORTS >> $(SUBDIR)$(FULLNAME).def; \ + emxexp $(OBJS) >> $(SUBDIR)$(FULLNAME).def' + SLIB_EXTRA_CMD='emximp -o $(SUBDIR)$(LIBPREF)$(FULLNAME)_dll.a $(SUBDIR)$(FULLNAME).def; \ + emximp -o $(SUBDIR)$(LIBPREF)$(FULLNAME)_dll.lib $(SUBDIR)$(FULLNAME).def;' + SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' + SLIB_INSTALL_LINKS= + SLIB_INSTALL_EXTRA_LIB='$(LIBPREF)$(FULLNAME)_dll.a $(LIBPREF)$(FULLNAME)_dll.lib' + enable dos_paths + enable_weak os2threads + ;; + gnu/kfreebsd) + add_cppflags -D_BSD_SOURCE + ;; + gnu) + ;; + qnx) + add_cppflags -D_QNX_SOURCE + network_extralibs="-lsocket" + ;; + symbian) + SLIBSUF=".dll" + enable dos_paths + add_cflags --include=$sysinclude/gcce/gcce.h -fvisibility=default + add_cppflags -D__GCCE__ -D__SYMBIAN32__ -DSYMBIAN_OE_POSIX_SIGNALS + add_ldflags -Wl,--target1-abs,--no-undefined \ + -Wl,-Ttext,0x80000,-Tdata,0x1000000 -shared \ + -Wl,--entry=_E32Startup -Wl,-u,_E32Startup + add_extralibs -l:eexe.lib -l:usrt2_2.lib -l:dfpaeabi.dso \ + -l:drtaeabi.dso -l:scppnwdl.dso -lsupc++ -lgcc \ + -l:libc.dso -l:libm.dso -l:euser.dso -l:libcrt0.lib + ;; + minix) + ;; + none) + ;; + *) + die "Unknown OS '$target_os'." + ;; +esac + +# test if creating links works +link_dest=$(mktemp -u $TMPDIR/dest_XXXXXXXX) +link_name=$(mktemp -u $TMPDIR/name_XXXXXXXX) +mkdir "$link_dest" +$ln_s "$link_dest" "$link_name" +touch "$link_dest/test_file" +if [ "$source_path" != "." ] && [ "$source_path" != "src" ] && ([ ! -d src ] || [ -L src ]) && [ -e "$link_name/test_file" ]; then + # create link to source path + [ -e src ] && rm src + $ln_s "$source_path" src + source_link=src +else + # creating directory links doesn't work + # fall back to using the full source path + source_link="$source_path" +fi +# cleanup +rm -r "$link_dest" +rm -r "$link_name" + +# determine libc flavour + +probe_libc(){ + pfx=$1 + pfx_no_=${pfx%_} + # uclibc defines __GLIBC__, so it needs to be checked before glibc. + if test_${pfx}cpp_condition features.h "defined __UCLIBC__"; then + eval ${pfx}libc_type=uclibc + add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 + elif test_${pfx}cpp_condition features.h "defined __GLIBC__"; then + eval ${pfx}libc_type=glibc + add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 + # MinGW headers can be installed on Cygwin, so check for newlib first. + elif test_${pfx}cpp_condition newlib.h "defined _NEWLIB_VERSION"; then + eval ${pfx}libc_type=newlib + add_${pfx}cppflags -U__STRICT_ANSI__ -D_XOPEN_SOURCE=600 + # MinGW64 is backwards compatible with MinGW32, so check for it first. + elif test_${pfx}cpp_condition _mingw.h "defined __MINGW64_VERSION_MAJOR"; then + eval ${pfx}libc_type=mingw64 + if test_${pfx}cpp_condition _mingw.h "__MINGW64_VERSION_MAJOR < 3"; then + add_compat msvcrt/snprintf.o + add_cflags "-include $source_path/compat/msvcrt/snprintf.h" + fi + add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 + eval test \$${pfx_no_}cc_type = "gcc" && + add_${pfx}cppflags -D__printf__=__gnu_printf__ + test_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 + add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 + elif test_${pfx}cpp_condition _mingw.h "defined __MINGW_VERSION" || + test_${pfx}cpp_condition _mingw.h "defined __MINGW32_VERSION"; then + eval ${pfx}libc_type=mingw32 + test_${pfx}cpp_condition _mingw.h "__MINGW32_MAJOR_VERSION > 3 || \ + (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION >= 15)" || + die "ERROR: MinGW32 runtime version must be >= 3.15." + add_${pfx}cppflags -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 + test_${pfx}cpp_condition _mingw.h "__MSVCRT_VERSION__ < 0x0700" && + add_${pfx}cppflags -D__MSVCRT_VERSION__=0x0700 + test_${pfx}cpp_condition windows.h "!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600" && + add_${pfx}cppflags -D_WIN32_WINNT=0x0600 + eval test \$${pfx_no_}cc_type = "gcc" && + add_${pfx}cppflags -D__printf__=__gnu_printf__ + add_${pfx}cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 + elif test_${pfx}cpp_condition crtversion.h "defined _VC_CRT_MAJOR_VERSION"; then + eval ${pfx}libc_type=msvcrt + if test_${pfx}cpp_condition crtversion.h "_VC_CRT_MAJOR_VERSION < 14"; then + if [ "$pfx" = host_ ]; then + add_host_cppflags -Dsnprintf=_snprintf + else + add_compat strtod.o strtod=avpriv_strtod + add_compat msvcrt/snprintf.o snprintf=avpriv_snprintf \ + _snprintf=avpriv_snprintf \ + vsnprintf=avpriv_vsnprintf + fi + fi + add_${pfx}cppflags -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS + # The MSVC 2010 headers (Win 7.0 SDK) set _WIN32_WINNT to + # 0x601 by default unless something else is set by the user. + # This can easily lead to us detecting functions only present + # in such new versions and producing binaries requiring windows 7.0. + # Therefore explicitly set the default to Vista unless the user has + # set something else on the command line. + # Don't do this if WINAPI_FAMILY is set and is set to a non-desktop + # family. For these cases, configure is free to use any functions + # found in the SDK headers by default. (Alternatively, we could force + # _WIN32_WINNT to 0x0602 in that case.) + test_${pfx}cpp_condition stdlib.h "defined(_WIN32_WINNT)" || + { test_${pfx}cpp < +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error not desktop +#endif +#endif +EOF + if [ "$pfx" = "" ]; then + check_func strtoll || add_cflags -Dstrtoll=_strtoi64 + check_func strtoull || add_cflags -Dstrtoull=_strtoui64 + fi + elif test_${pfx}cpp_condition stddef.h "defined __KLIBC__"; then + eval ${pfx}libc_type=klibc + elif test_${pfx}cpp_condition sys/cdefs.h "defined __BIONIC__"; then + eval ${pfx}libc_type=bionic + elif test_${pfx}cpp_condition sys/brand.h "defined LABELED_BRAND_NAME"; then + eval ${pfx}libc_type=solaris + add_${pfx}cppflags -D__EXTENSIONS__ -D_XOPEN_SOURCE=600 + elif test_${pfx}cpp_condition sys/version.h "defined __DJGPP__"; then + eval ${pfx}libc_type=djgpp + add_cppflags -U__STRICT_ANSI__ + add_cflags "-include $source_path/compat/djgpp/math.h" + add_compat djgpp/math.o + fi + test_${pfx}cc < +void *v = localtime_r; +EOF +test "$?" != 0 && test_${pfx}cc -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 < +void *v = localtime_r; +EOF + + eval test -n "\${${pfx}libc_type}" && enable ${pfx}libc_${libc_type} +} + +probe_libc +probe_libc host_ + +# hacks for compiler/libc/os combinations + +case $libc_type in + bionic) + add_compat strtod.o strtod=avpriv_strtod + ;; +esac + +check_compile_assert flt_lim "float.h limits.h" "DBL_MAX == (double)DBL_MAX" || + add_cppflags '-I\$(SRC_PATH)/compat/float' + +test_cpp_condition stdlib.h "defined(__PIC__) || defined(__pic__) || defined(PIC)" && enable_weak pic + +set_default libdir +: ${shlibdir_default:="$libdir"} +: ${pkgconfigdir_default:="$libdir/pkgconfig"} + +set_default $PATHS_LIST +set_default nm + +disabled optimizations || enabled ossfuzz || check_cflags -fomit-frame-pointer + +enable_weak_pic() { + disabled pic && return + enable pic + add_cppflags -DPIC + case "$target_os" in + mingw*|cygwin*|win*) + ;; + *) + add_cflags -fPIC + add_asflags -fPIC + ;; + esac +} + +enabled pic && enable_weak_pic + +test_cc <= 30"; then + : + elif ! test_cpp_condition stddef.h "defined __ARM_PCS || defined __SOFTFP__" && [ $target_os != darwin ]; then + case "${cross_prefix:-$cc}" in + *hardfloat*) enable vfp_args; fpabi=vfp ;; + *) check_ld "cc" vfp_args <= 9.0.18.0" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.8 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.9 ffnvcodec < 8.2" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.0.14.9 ffnvcodec < 8.1" "$ffnv_hdr_list" "" +fi + +check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" + +if ! disabled w32threads && ! enabled pthreads; then + check_func_headers "windows.h process.h" _beginthreadex && + check_type "windows.h" CONDITION_VARIABLE && + check_type "windows.h" INIT_ONCE && + enable w32threads || disable w32threads + if ! enabled w32threads && enabled winrt; then + check_func_headers "windows.h" CreateThread && + enable w32threads || disable w32threads + fi +fi + +# check for some common methods of building with pthread support +# do this before the optional library checks as some of them require pthreads +if ! disabled pthreads && ! enabled w32threads && ! enabled os2threads; then + if check_lib pthreads pthread.h pthread_join -pthread && + check_lib pthreads pthread.h pthread_create -pthread; then + add_cflags -pthread + elif check_lib pthreads pthread.h pthread_join -pthreads && + check_lib pthreads pthread.h pthread_create -pthreads; then + add_cflags -pthreads + elif check_lib pthreads pthread.h pthread_join -ldl -pthread && + check_lib pthreads pthread.h pthread_create -ldl -pthread; then + add_cflags -ldl -pthread + elif check_lib pthreads pthread.h pthread_join -lpthreadGC2 && + check_lib pthreads pthread.h pthread_create -lpthreadGC2; then + : + elif check_lib pthreads pthread.h pthread_join -lpthread && + check_lib pthreads pthread.h pthread_create -lpthread; then + : + elif check_func pthread_join && check_func pthread_create; then + enable pthreads + fi + check_cc pthreads "pthread.h" "static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER" + + if enabled pthreads; then + check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" $pthreads_extralibs + check_func pthread_cancel $pthreads_extralibs + fi +fi + +enabled zlib && { check_pkg_config zlib zlib "zlib.h" zlibVersion || + check_lib zlib zlib.h zlibVersion -lz; } +enabled bzlib && check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2 +enabled lzma && check_lib lzma lzma.h lzma_version_number -llzma + +# On some systems dynamic loading requires no extra linker flags +check_lib libdl dlfcn.h "dlopen dlsym" || check_lib libdl dlfcn.h "dlopen dlsym" -ldl + +check_lib libm math.h sin -lm + +atan2f_args=2 +copysign_args=2 +hypot_args=2 +ldexpf_args=2 +powf_args=2 + +for func in $MATH_FUNCS; do + eval check_mathfunc $func \${${func}_args:-1} $libm_extralibs +done + +for func in $COMPLEX_FUNCS; do + eval check_complexfunc $func \${${func}_args:-1} +done + +# these are off by default, so fail if requested and not available +enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; } +enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint +enabled decklink && { require_headers DeckLinkAPI.h && + { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a090500" || die "ERROR: Decklink API version must be >= 10.9.5."; } } +enabled frei0r && require_headers "frei0r.h dlfcn.h" +enabled gmp && require gmp gmp.h mpz_export -lgmp +enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init +enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; } +enabled ladspa && require_headers "ladspa.h dlfcn.h" +enabled libaom && require_pkg_config libaom "aom >= 1.0.0" aom/aom_codec.h aom_codec_version +enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new || + { enabled gpl && require_pkg_config libaribb24 aribb24 "aribb24/aribb24.h" arib_instance_new; } || + die "ERROR: libaribb24 requires version higher than 1.0.3 or --enable-gpl."; } +enabled lv2 && require_pkg_config lv2 lilv-0 "lilv/lilv.h" lilv_world_new +enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 +enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init +enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open +enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open +enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && + { check_lib libcelt celt/celt.h celt_decoder_create_custom -lcelt0 || + die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } +enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas +enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 +enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.4.0" "dav1d/dav1d.h" dav1d_version +enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open +enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new +enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion +enabled libfdk_aac && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen || + { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac && + warn "using libfdk without pkg-config"; } } +flite_extralibs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite" +enabled libflite && require libflite "flite/flite.h" flite_init $flite_extralibs +enabled fontconfig && enable libfontconfig +enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit +enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType +enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info +enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || + require libgme gme/gme.h gme_new_emu -lgme -lstdc++; } +enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do + check_lib libgsm "${gsm_hdr}" gsm_create -lgsm && break; + done || die "ERROR: libgsm not found"; } +enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc $pthreads_extralibs +enabled libklvanc && require libklvanc libklvanc/vanc.h klvanc_context_create -lklvanc +enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get +enabled liblensfun && require_pkg_config liblensfun lensfun lensfun.h lf_db_new +# While it may appear that require is being used as a pkg-config +# fallback for libmfx, it is actually being used to detect a different +# installation route altogether. If libmfx is installed via the Intel +# Media SDK or Intel Media Server Studio, these don't come with +# pkg-config support. Instead, users should make sure that the build +# can find the libraries and headers through other means. +enabled libmfx && { check_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit || + { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } } +enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load +enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs +enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_load || + require libmysofa mysofa.h mysofa_load -lmysofa $zlib_extralibs; } +enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc -lnppidei || + check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc -lnppidei || + die "ERROR: libnpp not found"; } +enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb +enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb +enabled libopencv && { check_headers opencv2/core/core_c.h && + { check_pkg_config libopencv opencv opencv2/core/core_c.h cvCreateImageHeader || + require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } || + require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; } +enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_api.h WelsGetCodecVersion +enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || + { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } +enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" +enabled libopus && { + enabled libopus_decoder && { + require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create + } + enabled libopus_encoder && { + require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create + } +} +enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new +enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo +enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket +enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++" +enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer +enabled libsmbclient && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init || + require libsmbclient libsmbclient.h smbc_init -lsmbclient; } +enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy -lstdc++ +enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr +enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp_init +enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init +enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket +enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow +enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate +enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg +enabled libtls && require_pkg_config libtls libtls tls.h tls_configure +enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && + { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || + die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl +enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf +enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc +enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && + require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init + +enabled libvpx && { + enabled libvpx_vp8_decoder && { + check_pkg_config libvpx_vp8_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx || + check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp8_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" + } + enabled libvpx_vp8_encoder && { + check_pkg_config libvpx_vp8_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx || + check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp8_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" + } + enabled libvpx_vp9_decoder && { + check_pkg_config libvpx_vp9_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || + check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" + } + enabled libvpx_vp9_encoder && { + check_pkg_config libvpx_vp9_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || + check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" + } + if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then + die "libvpx enabled but no supported decoders found" + fi +} + +enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack +enabled libwebp && { + enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion + enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; } +enabled libx264 && { check_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode || + { require libx264 "stdint.h x264.h" x264_encoder_encode "-lx264 $pthreads_extralibs $libm_extralibs" && + warn "using libx264 without pkg-config"; } } && + require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && + check_cpp_condition libx262 x264.h "X264_MPEG2" +enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && + require_cpp_condition libx265 x265.h "X265_BUILD >= 68" +enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" +enabled libxavs2 && require_pkg_config libxavs2 "xavs2 >= 1.3.0" "stdint.h xavs2.h" xavs2_api_get +enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore +enabled libzimg && require_pkg_config libzimg "zimg >= 2.7.0" zimg.h zimg_get_api_version +enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new +enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && + { test_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || + enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; } +enabled libxml2 && require_pkg_config libxml2 libxml-2.0 libxml2/libxml/xmlversion.h xmlCheckVersion +enabled mbedtls && { check_pkg_config mbedtls mbedtls mbedtls/x509_crt.h mbedtls_x509_crt_init || + check_pkg_config mbedtls mbedtls mbedtls/ssl.h mbedtls_ssl_init || + check_lib mbedtls mbedtls/ssl.h mbedtls_ssl_init -lmbedtls -lmbedx509 -lmbedcrypto || + die "ERROR: mbedTLS not found"; } +enabled mediacodec && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; } +enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host || + { ! enabled cross_compile && + add_cflags -isystem/opt/vc/include/ -isystem/opt/vc/include/interface/vmcs_host/linux -isystem/opt/vc/include/interface/vcos/pthreads -fgnu89-inline && + add_ldflags -L/opt/vc/lib/ && + check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } || + die "ERROR: mmal not found" && + check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; } +enabled openal && { { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do + check_lib openal 'AL/al.h' alGetError "${al_extralibs}" && break; done } || + die "ERROR: openal not found"; } && + { test_cpp_condition "AL/al.h" "defined(AL_VERSION_1_1)" || + die "ERROR: openal must be installed and version must be 1.1 or compatible"; } +enabled opencl && { check_pkg_config opencl OpenCL CL/cl.h clEnqueueNDRangeKernel || + check_lib opencl OpenCL/cl.h clEnqueueNDRangeKernel -Wl,-framework,OpenCL || + check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL || + die "ERROR: opencl not found"; } && + { test_cpp_condition "OpenCL/cl.h" "defined(CL_VERSION_1_2)" || + test_cpp_condition "CL/cl.h" "defined(CL_VERSION_1_2)" || + die "ERROR: opencl must be installed and version must be 1.2 or compatible"; } +enabled opengl && { check_lib opengl GL/glx.h glXGetProcAddress "-lGL" || + check_lib opengl windows.h wglGetProcAddress "-lopengl32 -lgdi32" || + check_lib opengl OpenGL/gl3.h glGetError "-Wl,-framework,OpenGL" || + check_lib opengl ES2/gl.h glGetError "-isysroot=${sysroot} -Wl,-framework,OpenGLES" || + die "ERROR: opengl not found." + } +enabled omx && require_headers OMX_Core.h +enabled omx_rpi && { check_headers OMX_Core.h || + { ! enabled cross_compile && add_cflags -isystem/opt/vc/include/IL && check_headers OMX_Core.h ; } || + die "ERROR: OpenMAX IL headers not found"; } && enable omx +enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl || + check_pkg_config openssl openssl openssl/ssl.h SSL_library_init || + check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || + check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || + check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || + die "ERROR: openssl not found"; } +enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init +enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/rk_mpi.h mpp_create && + require_pkg_config rockchip_mpp "rockchip_mpp >= 1.3.7" rockchip/rk_mpi.h mpp_create && + { enabled libdrm || + die "ERROR: rkmpp requires --enable-libdrm"; } + } +enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init + + +if enabled gcrypt; then + GCRYPT_CONFIG="${cross_prefix}libgcrypt-config" + if "${GCRYPT_CONFIG}" --version > /dev/null 2>&1; then + gcrypt_cflags=$("${GCRYPT_CONFIG}" --cflags) + gcrypt_extralibs=$("${GCRYPT_CONFIG}" --libs) + check_func_headers gcrypt.h gcry_mpi_new $gcrypt_cflags $gcrypt_extralibs || + die "ERROR: gcrypt not found" + add_cflags $gcrypt_cflags + else + require gcrypt gcrypt.h gcry_mpi_new -lgcrypt + fi +fi + +if enabled sdl2; then + SDL2_CONFIG="${cross_prefix}sdl2-config" + test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent + if disabled sdl2 && "${SDL2_CONFIG}" --version > /dev/null 2>&1; then + sdl2_cflags=$("${SDL2_CONFIG}" --cflags) + sdl2_extralibs=$("${SDL2_CONFIG}" --libs) + test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && + test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && + check_func_headers SDL_events.h SDL_PollEvent $sdl2_extralibs $sdl2_cflags && + enable sdl2 + fi + if test $target_os = "mingw32"; then + sdl2_extralibs=$(filter_out '-mwindows' $sdl2_extralibs) + fi +fi + +if enabled decklink; then + case $target_os in + mingw32*|mingw64*|win32|win64) + decklink_outdev_extralibs="$decklink_outdev_extralibs -lole32 -loleaut32" + decklink_indev_extralibs="$decklink_indev_extralibs -lole32 -loleaut32" + ;; + esac +fi + +enabled securetransport && + check_func SecIdentityCreate "-Wl,-framework,CoreFoundation -Wl,-framework,Security" && + check_lib securetransport "Security/SecureTransport.h Security/Security.h" "SSLCreateContext" "-Wl,-framework,CoreFoundation -Wl,-framework,Security" || + disable securetransport + +enabled securetransport && + check_func SecItemImport "-Wl,-framework,CoreFoundation -Wl,-framework,Security" + +enabled schannel && + check_func_headers "windows.h security.h" InitializeSecurityContext -DSECURITY_WIN32 -lsecur32 && + test_cpp_condition winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && + schannel_extralibs="-lsecur32" || + disable schannel + +makeinfo --version > /dev/null 2>&1 && enable makeinfo || disable makeinfo +enabled makeinfo \ + && [ 0$(makeinfo --version | grep "texinfo" | sed 's/.*texinfo[^0-9]*\([0-9]*\)\..*/\1/') -ge 5 ] \ + && enable makeinfo_html || disable makeinfo_html +disabled makeinfo_html && texi2html --help 2> /dev/null | grep -q 'init-file' && enable texi2html || disable texi2html +perl -v > /dev/null 2>&1 && enable perl || disable perl +pod2man --help > /dev/null 2>&1 && enable pod2man || disable pod2man +rsync --help 2> /dev/null | grep -q 'contimeout' && enable rsync_contimeout || disable rsync_contimeout + +# check V4L2 codecs available in the API +check_headers linux/fb.h +check_headers linux/videodev2.h +test_code cc linux/videodev2.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete +check_cc v4l2_m2m linux/videodev2.h "int i = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_BUF_FLAG_LAST;" +check_cc vc1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VC1_ANNEX_G;" +check_cc mpeg1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG1;" +check_cc mpeg2_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2;" +check_cc mpeg4_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG4;" +check_cc hevc_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC;" +check_cc h263_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H263;" +check_cc h264_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H264;" +check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;" +check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" + +check_headers sys/videoio.h +test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete + +check_lib user32 "windows.h winuser.h" GetShellWindow -luser32 +check_lib vfw32 "windows.h vfw.h" capCreateCaptureWindow -lvfw32 +# check that WM_CAP_DRIVER_CONNECT is defined to the proper value +# w32api 3.12 had it defined wrong +check_cpp_condition vfwcap_defines vfw.h "WM_CAP_DRIVER_CONNECT > WM_USER" + +check_type "dshow.h" IBaseFilter + +# check for ioctl_meteor.h, ioctl_bt848.h and alternatives +check_headers "dev/bktr/ioctl_meteor.h dev/bktr/ioctl_bt848.h" || + check_headers "machine/ioctl_meteor.h machine/ioctl_bt848.h" || + check_headers "dev/video/meteor/ioctl_meteor.h dev/video/bktr/ioctl_bt848.h" || + check_headers "dev/ic/bt8xx.h" + +if check_struct sys/soundcard.h audio_buf_info bytes; then + enable_sanitized sys/soundcard.h +else + test_cc -D__BSD_VISIBLE -D__XSI_VISIBLE < + audio_buf_info abc; +EOF +fi + +enabled alsa && check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || + check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound + +enabled libjack && + require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range + +enabled sndio && check_lib sndio sndio.h sio_open -lsndio + +if enabled libcdio; then + check_pkg_config libcdio libcdio_paranoia "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open || + check_pkg_config libcdio libcdio_paranoia "cdio/paranoia/cdda.h cdio/paranoia/paranoia.h" cdio_cddap_open || + check_lib libcdio "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open -lcdio_paranoia -lcdio_cdda -lcdio || + check_lib libcdio "cdio/paranoia/cdda.h cdio/paranoia/paranoia.h" cdio_cddap_open -lcdio_paranoia -lcdio_cdda -lcdio || + die "ERROR: No usable libcdio/cdparanoia found" +fi + +enabled libxcb && check_pkg_config libxcb "xcb >= 1.4" xcb/xcb.h xcb_connect || + disable libxcb_shm libxcb_shape libxcb_xfixes + +if enabled libxcb; then + enabled libxcb_shm && check_pkg_config libxcb_shm xcb-shm xcb/shm.h xcb_shm_attach + enabled libxcb_shape && check_pkg_config libxcb_shape xcb-shape xcb/shape.h xcb_shape_get_rectangles + enabled libxcb_xfixes && check_pkg_config libxcb_xfixes xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image +fi + +check_func_headers "windows.h" CreateDIBSection "$gdigrab_indev_extralibs" + +# d3d11va requires linking directly to dxgi and d3d11 if not building for +# the desktop api partition +test_cpp < +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#error desktop, not uwp +#else +// WINAPI_FAMILY_APP, WINAPI_FAMILY_PHONE_APP => UWP +#endif +#else +#error no family set +#endif +EOF + +enabled vaapi && + check_pkg_config vaapi "libva >= 0.35.0" "va/va.h" vaInitialize + +if enabled vaapi; then + check_pkg_config vaapi_drm "libva-drm" "va/va_drm.h" vaGetDisplayDRM + + if enabled xlib; then + check_pkg_config vaapi_x11 "libva-x11" "va/va_x11.h" vaGetDisplay + fi + + check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)" + + check_type "va/va.h va/va_dec_hevc.h" "VAPictureParameterBufferHEVC" + check_struct "va/va.h" "VADecPictureParameterBufferVP9" bit_depth + check_struct "va/va.h va/va_vpp.h" "VAProcPipelineCaps" rotation_flags + check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC" + check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG" + check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8" + check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9" +fi + +if enabled_all opencl libdrm ; then + check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" && + enable opencl_drm_beignet + check_func_headers "CL/cl_ext.h" clImportMemoryARM && + enable opencl_drm_arm +fi + +if enabled_all opencl vaapi ; then + if enabled opencl_drm_beignet ; then + enable opencl_vaapi_beignet + else + check_type "CL/cl.h CL/cl_va_api_media_sharing_intel.h" "clCreateFromVA_APIMediaSurfaceINTEL_fn" && + enable opencl_vaapi_intel_media + fi +fi + +if enabled_all opencl dxva2 ; then + check_type "CL/cl_dx9_media_sharing.h" cl_dx9_surface_info_khr && + enable opencl_dxva2 +fi + +if enabled_all opencl d3d11va ; then + check_type "CL/cl_d3d11.h" clGetDeviceIDsFromD3D11KHR_fn && + enable opencl_d3d11 +fi + +enabled vdpau && + check_cpp_condition vdpau vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" + +enabled vdpau && + check_lib vdpau_x11 "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau -lX11 + +enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd + +if enabled x86; then + case $target_os in + mingw32*|mingw64*|win32|win64|linux|cygwin*) + ;; + *) + disable ffnvcodec cuvid nvdec nvenc + ;; + esac +elif enabled ppc64 && ! enabled bigendian; then + case $target_os in + linux) + ;; + *) + disable ffnvcodec cuvid nvdec nvenc + ;; + esac +else + disable ffnvcodec cuvid nvdec nvenc +fi + +enabled ffnvcodec && enable cuda + +enabled nvenc && + test_cc -I$source_path < +NV_ENCODE_API_FUNCTION_LIST flist; +void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } }; } +int main(void) { return 0; } +EOF + +enabled amf && + check_cpp_condition amf "AMF/core/Version.h" \ + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" + +# Funny iconv installations are not unusual, so check it after all flags have been set +if enabled libc_iconv; then + check_func_headers iconv.h iconv +elif enabled iconv; then + check_func_headers iconv.h iconv || check_lib iconv iconv.h iconv -liconv +fi + +enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel" + +# add some useful compiler flags if supported +check_cflags -Wdeclaration-after-statement +check_cflags -Wall +check_cflags -Wdisabled-optimization +check_cflags -Wpointer-arith +check_cflags -Wredundant-decls +check_cflags -Wwrite-strings +check_cflags -Wtype-limits +check_cflags -Wundef +check_cflags -Wmissing-prototypes +check_cflags -Wno-pointer-to-int-cast +check_cflags -Wstrict-prototypes +check_cflags -Wempty-body + +if enabled extra_warnings; then + check_cflags -Wcast-qual + check_cflags -Wextra + check_cflags -Wpedantic +fi + +check_disable_warning(){ + warning_flag=-W${1#-Wno-} + test_cflags $unknown_warning_flags $warning_flag && add_cflags $1 +} + +test_cflags -Werror=unused-command-line-argument && + append unknown_warning_flags "-Werror=unused-command-line-argument" +test_cflags -Werror=unknown-warning-option && + append unknown_warning_flags "-Werror=unknown-warning-option" + +check_disable_warning -Wno-parentheses +check_disable_warning -Wno-switch +check_disable_warning -Wno-format-zero-length +check_disable_warning -Wno-pointer-sign +check_disable_warning -Wno-unused-const-variable +check_disable_warning -Wno-bool-operation +check_disable_warning -Wno-char-subscripts + +check_disable_warning_headers(){ + warning_flag=-W${1#-Wno-} + test_cflags $warning_flag && add_cflags_headers $1 +} + +check_disable_warning_headers -Wno-deprecated-declarations +check_disable_warning_headers -Wno-unused-variable + +test_cc < $TMPV + if test_ldflags -Wl,${version_script},$TMPV; then + append SHFLAGS '-Wl,${version_script},\$(SUBDIR)lib\$(NAME).ver' + quotes='""' + test_cc <= 1400" && + add_cflags -Qansi-alias + # Some inline asm is not compilable in debug + if enabled debug; then + disable ebp_available + disable ebx_available + fi + fi + # msvcrt10 x64 incorrectly enables log2, only msvcrt12 (MSVC 2013) onwards actually has log2. + check_cpp_condition log2 crtversion.h "_VC_CRT_MAJOR_VERSION >= 12" + # The CRT headers contain __declspec(restrict) in a few places, but if redefining + # restrict, this might break. MSVC 2010 and 2012 fail with __declspec(__restrict) + # (as it ends up if the restrict redefine is done before including stdlib.h), while + # MSVC 2013 and newer can handle it fine. + # If this declspec fails, force including stdlib.h before the restrict redefinition + # happens in config.h. + if [ $restrict_keyword != restrict ]; then + test_cc <= 190024218" || + check_cflags -d2SSAOptimizer- + # enable utf-8 source processing on VS2015 U2 and newer + test_cpp_condition windows.h "_MSC_FULL_VER >= 190023918" && + add_cflags -utf-8 +fi + +for pfx in "" host_; do + varname=${pfx%_}cc_type + eval "type=\$$varname" + if [ "$type" = "msvc" ]; then + test_${pfx}cc < Makefile + +esc(){ + echo "$*" | sed 's/%/%25/g;s/:/%3a/g' +} + +echo "config:$arch:$subarch:$cpu:$target_os:$(esc $cc_ident):$(esc $FFMPEG_CONFIGURATION)" > ffbuild/config.fate + +enabled stripping || strip="echo skipping strip" +enabled stripping || striptype="" + +config_files="$TMPH ffbuild/config.mak doc/config.texi" + +cat > ffbuild/config.mak <> ffbuild/config.mak' $LIBRARY_LIST + +for entry in $LIBRARY_LIST $PROGRAM_LIST $EXTRALIBS_LIST; do + eval echo "EXTRALIBS-${entry}=\$${entry}_extralibs" >> ffbuild/config.mak +done + +cat > $TMPH <>$TMPH + +test -n "$malloc_prefix" && + echo "#define MALLOC_PREFIX $malloc_prefix" >>$TMPH + +if enabled x86asm; then + append config_files $TMPASM + cat > $TMPASM <> $TMPH + + +mkdir -p doc +mkdir -p tests +mkdir -p tests/api +echo "@c auto-generated by configure - do not modify! " > doc/config.texi + +print_config ARCH_ "$config_files" $ARCH_LIST +print_config HAVE_ "$config_files" $HAVE_LIST +print_config CONFIG_ "$config_files" $CONFIG_LIST \ + $CONFIG_EXTRA \ + $ALL_COMPONENTS \ + +echo "#endif /* FFMPEG_CONFIG_H */" >> $TMPH +echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.mak + +# Do not overwrite an unchanged config.h to avoid superfluous rebuilds. +cp_if_changed $TMPH config.h +touch ffbuild/.config + +enabled x86asm && cp_if_changed $TMPASM config.asm + +cat > $TMPH <> $TMPH + +cp_if_changed $TMPH libavutil/avconfig.h + +# full_filter_name_foo=vf_foo +# full_filter_name_bar=asrc_bar +# ... +eval "$(sed -n "s/^extern AVFilter ff_\([avfsinkrc]\{2,5\}\)_\(.*\);/full_filter_name_\2=\1_\2/p" $source_path/libavfilter/allfilters.c)" + +# generate the lists of enabled components +print_enabled_components(){ + file=$1 + struct_name=$2 + name=$3 + shift 3 + echo "static const $struct_name * const $name[] = {" > $TMPH + for c in $*; do + if enabled $c; then + case $name in + filter_list) + eval c=\$full_filter_name_${c%_filter} + ;; + indev_list) + c=${c%_indev}_demuxer + ;; + outdev_list) + c=${c%_outdev}_muxer + ;; + esac + printf " &ff_%s,\n" $c >> $TMPH + fi + done + if [ "$name" = "filter_list" ]; then + for c in asrc_abuffer vsrc_buffer asink_abuffer vsink_buffer; do + printf " &ff_%s,\n" $c >> $TMPH + done + fi + echo " NULL };" >> $TMPH + cp_if_changed $TMPH $file +} + +print_enabled_components libavfilter/filter_list.c AVFilter filter_list $FILTER_LIST +print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST +print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST +print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST +print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST +print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST +print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST +print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST +print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST + +# Settings for pkg-config files + +cat > $TMPH <> $TMPH +done + +cp_if_changed $TMPH ffbuild/config.sh From a948a512326aafa55f75310287b2ff16bf92a051 Mon Sep 17 00:00:00 2001 From: Reza Mir Date: Mon, 9 Aug 2021 17:40:52 -0400 Subject: [PATCH 03/11] Apply missing parts of our changes in dashenc.c --- libavformat/dashenc.c | 57 +++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 42ca768f0c414..063fe70a88679 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -149,6 +149,7 @@ typedef struct OutputStream { int64_t gop_size; AVRational sar; int coding_dependency; + struct AVAES *aes_context; int aes_encrypt; uint8_t aes_iv[KEYSIZE]; @@ -217,11 +218,11 @@ typedef struct DASHContext { AVRational min_playback_rate; AVRational max_playback_rate; int64_t update_period; + int start_segment; int64_t seg_duration_ts; int64_t start_fragment_index; int64_t frame_duration_ts; - int start_segment; // Pass-through options to movenc -PTT char *encryption_scheme_str; @@ -1825,6 +1826,20 @@ static int dash_init(AVFormatContext *s) // skip_sidx : Reduce bitrate overhead // skip_trailer : Avoids growing memory usage with time av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND); + else if (c->start_segment > 1) { + //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+frag_discont", 0); + av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+frag_discont", 0); + } else { + //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0); + /* + * Notes: + * - frag_custom+dash+delay_moov - correct segments, single moof (frames reordered) + * - frag_every_frame+dash+delay_moov - moof per frame, correct data + */ + } + + /* else { if (c->global_sidx) { if (c->start_segment > 1) { @@ -1840,6 +1855,7 @@ static int dash_init(AVFormatContext *s) } } } + */ if (c->start_fragment_index > 1) { char start_fragment_index_str[128]; @@ -2424,6 +2440,20 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) s->prev_pts = pkt->pts; + + if (os->parser && + (os->frag_type == FRAG_TYPE_PFRAMES || + as->trick_idx >= 0)) { + // Parse the packets only in scenarios where it's needed + uint8_t *data; + int size; + av_parser_parse2(os->parser, os->parser_avctx, + &data, &size, pkt->data, pkt->size, + pkt->pts, pkt->dts, pkt->pos); + + os->coding_dependency |= os->parser->pict_type != AV_PICTURE_TYPE_I; + } + #if 0 av_log(s, AV_LOG_INFO, "dash_write_packet is_key=%d pts=%"PRId64" duration=%"PRId64" start_pts=%"PRId64 " max_pts=%"PRId64" elapsed_duration=%"PRId64" seg_duration_ts=%"PRId64" frame_duration_variation=%"PRId64 @@ -2441,23 +2471,12 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) * or interval around expected PTS. */ - - if (os->parser && - (os->frag_type == FRAG_TYPE_PFRAMES || - as->trick_idx >= 0)) { - // Parse the packets only in scenarios where it's needed - uint8_t *data; - int size; - av_parser_parse2(os->parser, os->parser_avctx, - &data, &size, pkt->data, pkt->size, - pkt->pts, pkt->dts, pkt->pos); - - os->coding_dependency |= os->parser->pict_type != AV_PICTURE_TYPE_I; - } - if (pkt->flags & AV_PKT_FLAG_KEY && os->packets_written && - av_compare_ts(elapsed_duration, st->time_base, - seg_end_duration, AV_TIME_BASE_Q) >= 0) { + elapsed_duration >= c->seg_duration_ts) + /* av_compare_ts(elapsed_duration, st->time_base, + seg_end_duration, AV_TIME_BASE_Q) >= 0) + */ + { if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { c->last_duration = av_rescale_q(pkt->pts - os->start_pts, st->time_base, @@ -2560,6 +2579,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) snprintf(os->temp_path, sizeof(os->temp_path), use_rename ? "%s.tmp" : "%s", os->full_path); set_http_options(&opts, c); + sprintf(stream_index, "%d", pkt->stream_index); + av_dict_set(&opts, "stream_index", stream_index, 0); ret = dashenc_io_open(s, &os->out, os->temp_path, &opts); av_dict_free(&opts); if (ret < 0) { @@ -2574,7 +2595,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) } //write out the data immediately in streaming mode - if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) { + if (1 /* PENDING(SSS) figure out flag */ || (c->streaming && os->segment_type == SEGMENT_TYPE_MP4)) { int len = 0; uint8_t *buf = NULL; avio_flush(os->ctx->pb); From 47ca02847dc49ab107d12172a82dae90a48f2618 Mon Sep 17 00:00:00 2001 From: Reza Mir Date: Mon, 9 Aug 2021 23:32:36 -0400 Subject: [PATCH 04/11] Another fix in dashenc.c --- libavformat/dashenc.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 063fe70a88679..fd5311c34bbe8 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1823,23 +1823,10 @@ static int dash_init(AVFormatContext *s) if (os->segment_type == SEGMENT_TYPE_MP4) { if (c->streaming) + // frag_every_frame : Allows lower latency streaming // skip_sidx : Reduce bitrate overhead // skip_trailer : Avoids growing memory usage with time - av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND); - else if (c->start_segment > 1) { - //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+frag_discont", 0); - av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+frag_discont", 0); - } else { - //av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); - av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0); - /* - * Notes: - * - frag_custom+dash+delay_moov - correct segments, single moof (frames reordered) - * - frag_every_frame+dash+delay_moov - moof per frame, correct data - */ - } - - /* + av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0); else { if (c->global_sidx) { if (c->start_segment > 1) { @@ -1855,7 +1842,6 @@ static int dash_init(AVFormatContext *s) } } } - */ if (c->start_fragment_index > 1) { char start_fragment_index_str[128]; From 19323883abb7c1b78acc47384141722398e42082 Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Thu, 12 Aug 2021 17:26:35 -0400 Subject: [PATCH 05/11] New configure.debug is added --- configure.debug | 522 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 352 insertions(+), 170 deletions(-) diff --git a/configure.debug b/configure.debug index a9bfa1ca3f9f1..bbb662f0ac76f 100755 --- a/configure.debug +++ b/configure.debug @@ -190,9 +190,9 @@ External library support: Using any of the following switches will allow FFmpeg to link to the corresponding external library. All the components depending on that library will become enabled, if all their other dependencies are met and they are not - explicitly disabled. E.g. --enable-libwavpack will enable linking to - libwavpack and allow the libwavpack encoder to be built, unless it is - specifically disabled with --disable-encoder=libwavpack. + explicitly disabled. E.g. --enable-libopus will enable linking to + libopus and allow the libopus encoder to be built, unless it is + specifically disabled with --disable-encoder=libopus. Note that only the system libraries are auto-detected. All the other external libraries must be explicitly enabled. @@ -236,6 +236,7 @@ External library support: --enable-libfontconfig enable libfontconfig, useful for drawtext filter [no] --enable-libfreetype enable libfreetype, needed for drawtext filter [no] --enable-libfribidi enable libfribidi, improves drawtext filter [no] + --enable-libglslang enable GLSL->SPIRV compilation via libglslang [no] --enable-libgme enable Game Music Emu via libgme [no] --enable-libgsm enable GSM de/encoding via libgsm [no] --enable-libiec61883 enable iec61883 via libiec61883 [no] @@ -252,8 +253,13 @@ External library support: --enable-libopenh264 enable H.264 encoding via OpenH264 [no] --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] --enable-libopenmpt enable decoding tracked files via libopenmpt [no] + --enable-libopenvino enable OpenVINO as a DNN module backend + for DNN based filters like dnn_processing [no] --enable-libopus enable Opus de/encoding via libopus [no] --enable-libpulse enable Pulseaudio input via libpulse [no] + --enable-librabbitmq enable RabbitMQ library [no] + --enable-librav1e enable AV1 encoding via rav1e [no] + --enable-librist enable RIST via librist [no] --enable-librsvg enable SVG rasterization via librsvg [no] --enable-librubberband enable rubberband needed for rubberband filter [no] --enable-librtmp enable RTMP[E] support via librtmp [no] @@ -264,6 +270,7 @@ External library support: --enable-libspeex enable Speex de/encoding via libspeex [no] --enable-libsrt enable Haivision SRT protocol via libsrt [no] --enable-libssh enable SFTP protocol via libssh [no] + --enable-libsvtav1 enable AV1 encoding via SVT [no] --enable-libtensorflow enable TensorFlow as a DNN module backend for DNN based filters like sr [no] --enable-libtesseract enable Tesseract, needed for ocr filter [no] @@ -271,6 +278,7 @@ External library support: --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -278,7 +286,6 @@ External library support: --enable-libvorbis enable Vorbis en/decoding via libvorbis, native implementation exists [no] --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] - --enable-libwavpack enable wavpack encoding via libwavpack [no] --enable-libwebp enable WebP encoding via libwebp [no] --enable-libx264 enable H.264 encoding via x264 [no] --enable-libx265 enable HEVC encoding via x265 [no] @@ -301,6 +308,7 @@ External library support: --enable-mbedtls enable mbedTLS, needed for https support if openssl, gnutls or libtls is not used [no] --enable-mediacodec enable Android MediaCodec support [no] + --enable-mediafoundation enable encoding via MediaFoundation [auto] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] --enable-opencl enable OpenCL processing [no] @@ -315,6 +323,7 @@ External library support: --disable-securetransport disable Secure Transport, needed for TLS support on OSX if openssl and gnutls are not used [autodetect] --enable-vapoursynth enable VapourSynth demuxer [no] + --enable-vulkan enable Vulkan code [no] --disable-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] @@ -481,6 +490,7 @@ Developer options (useful when working on FFmpeg itself): --ignore-tests=TESTS comma-separated list (without "fate-" prefix in the name) of tests whose result is ignored --enable-linux-perf enable Linux Performance Monitor API + --disable-large-tests disable tests that use a large amount of memory NOTE: Object files are built at the place where configure is launched. EOF @@ -526,7 +536,7 @@ die(){ If you think configure made a mistake, make sure you are using the latest version from Git. If the latest version fails, report the problem to the -ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net. +ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.libera.chat. EOF if disabled logging; then cat <&1 | grep -q xlc; then _type=xlc _ident=$($_cc -qversion 2>/dev/null | head -n1) # _cflags_speed='-O5' - _cflags_size='-O5 -qcompact' +# _cflags_size='-O5 -qcompact' elif $_cc --vsn 2>/dev/null | grep -Eq "ARM (C/C\+\+ )?Compiler"; then test -d "$sysroot" || die "No valid sysroot specified." _type=armcc @@ -4549,7 +4665,7 @@ probe_cc(){ _DEPFLAGS='-xM1 -xc99' _ldflags='-std=c99' # _cflags_speed='-O5' - _cflags_size='-O5 -xspace' +# _cflags_size='-O5 -xspace' _flags_filter=suncc_flags elif $_cc -v 2>&1 | grep -q 'PathScale\|Path64'; then _type=pathscale @@ -4578,7 +4694,7 @@ probe_cc(){ # Not only is O3 broken on 13.x+ but it is slower on all previous # versions (tested) as well. # _cflags_speed="-O2" - _cflags_size="-O1 -Oi" # -O1 without -Oi miscompiles stuff +# _cflags_size="-O1 -Oi" # -O1 without -Oi miscompiles stuff if $_cc 2>&1 | grep -q Linker; then _ld_o='-out:$@' else @@ -4609,12 +4725,16 @@ probe_cc(){ _ld_path='-libpath:' elif $_cc -nologo- 2>&1 | grep -q Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then _type=msvc - _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') + if $_cc -nologo- 2>&1 | grep -q Microsoft; then + _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') + else + _ident=$($_cc --version 2>/dev/null | head -n1 | tr -d '\r') + fi _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs' # _cflags_speed="-O2" - _cflags_size="-O1" - _cflags_noopt="-O1" +# _cflags_size="-O1" +# _cflags_noopt="-O1" if $_cc -nologo- 2>&1 | grep -q Linker; then _ld_o='-out:$@' else @@ -4632,7 +4752,7 @@ probe_cc(){ _ident=$($_cc --version | head -n1) _depflags='-MMD' # _cflags_speed='-O4' - _cflags_size='-O2' +# _cflags_size='-O2' _flags_filter=cparser_flags fi @@ -4749,7 +4869,7 @@ fi if test "$cpu" = host; then enabled cross_compile && - die "--cpu=host makes no sense when cross-compiling." + warn "--cpu=host makes no sense when cross-compiling." case "$cc_type" in gcc|llvm_gcc) @@ -4932,8 +5052,6 @@ elif enabled bfin; then elif enabled mips; then - cpuflags="-march=$cpu" - if [ "$cpu" != "generic" ]; then disable mips32r2 disable mips32r5 @@ -4942,19 +5060,53 @@ elif enabled mips; then disable mips64r6 disable loongson2 disable loongson3 + disable mipsdsp + disable mipsdspr2 + + cpuflags="-march=$cpu" case $cpu in - 24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf) + # General ISA levels + mips1|mips3) + ;; + mips32r2) enable mips32r2 - disable msa ;; - p5600|i6400|p6600) - disable mipsdsp - disable mipsdspr2 + mips32r5) + enable mips32r2 + enable mips32r5 ;; - loongson*) - enable loongson2 + mips64r2|mips64r5) + enable mips64r2 enable loongson3 + ;; + # Cores from MIPS(MTI) + 24kc) + disable mipsfpu + enable mips32r2 + ;; + 24kf*|24kec|34kc|74Kc|1004kc) + enable mips32r2 + ;; + 24kef*|34kf*|1004kf*) + enable mipsdsp + enable mips32r2 + ;; + p5600) + enable mips32r2 + enable mips32r5 + check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" + ;; + i6400) + enable mips64r6 + check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + p6600) + enable mips64r6 + check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + # Cores from Loongson + loongson2e|loongson2f|loongson3*) enable local_aligned enable simd_align_16 enable fast_64bit @@ -4962,75 +5114,42 @@ elif enabled mips; then enable fast_cmov enable fast_unaligned disable aligned_stack - disable mipsdsp - disable mipsdspr2 # When gcc version less than 5.3.0, add -fno-expensive-optimizations flag. - if [ $cc == gcc ]; then - gcc_version=$(gcc -dumpversion) - if [ "$(echo "$gcc_version 5.3.0" | tr " " "\n" | sort -rV | head -n 1)" == "$gcc_version" ]; then - expensive_optimization_flag="" - else + if test "$cc_type" = "gcc"; then + case $gcc_basever in + 2|2.*|3.*|4.*|5.0|5.1|5.2) expensive_optimization_flag="-fno-expensive-optimizations" - fi + ;; + *) + expensive_optimization_flag="" + ;; + esac fi + case $cpu in loongson3*) + enable loongson3 cpuflags="-march=loongson3a -mhard-float $expensive_optimization_flag" ;; loongson2e) + enable loongson2 cpuflags="-march=loongson2e -mhard-float $expensive_optimization_flag" ;; loongson2f) + enable loongson2 cpuflags="-march=loongson2f -mhard-float $expensive_optimization_flag" ;; esac ;; *) - # Unknown CPU. Disable everything. - warn "unknown CPU. Disabling all MIPS optimizations." - disable mipsfpu - disable mipsdsp - disable mipsdspr2 - disable msa - disable mmi + warn "unknown MIPS CPU" ;; esac - case $cpu in - 24kc) - disable mipsfpu - disable mipsdsp - disable mipsdspr2 - ;; - 24kf*) - disable mipsdsp - disable mipsdspr2 - ;; - 24kec|34kc|1004kc) - disable mipsfpu - disable mipsdspr2 - ;; - 24kef*|34kf*|1004kf*) - disable mipsdspr2 - ;; - 74kc) - disable mipsfpu - ;; - p5600) - enable mips32r5 - check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" - ;; - i6400) - enable mips64r6 - check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" - ;; - p6600) - enable mips64r6 - check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" - ;; - esac else - # We do not disable anything. Is up to the user to disable the unwanted features. + disable mipsdsp + disable mipsdspr2 + # Disable DSP stuff for generic CPU, it can't be detected at runtime. warn 'generic cpu selected' fi @@ -5268,6 +5387,7 @@ case $target_os in ;; openbsd|bitrig) disable symver + enable section_data_rel_ro striptype="" SHFLAGS='-shared' SLIB_INSTALL_NAME='$(SLIBNAME).$(LIBMAJOR).$(LIBMINOR)' @@ -5306,6 +5426,11 @@ case $target_os in fi version_script='-exported_symbols_list' VERSION_SCRIPT_POSTPROCESS_CMD='tr " " "\n" | sed -n /global:/,/local:/p | grep ";" | tr ";" "\n" | sed -E "s/(.+)/_\1/g" | sed -E "s/(.+[^*])$$$$/\1*/"' + # Workaround for Xcode 11 -fstack-check bug + if enabled clang; then + clang_version=$($cc -dumpversion) + test ${clang_version%%.*} -eq 11 && add_cflags -fno-stack-check + fi ;; msys*) die "Native MSYS builds are discouraged, please use the MINGW environment." @@ -5771,28 +5896,42 @@ EOF elif enabled mips; then - enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"' - enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' - enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"' - - # Enable minimum ISA based on selected options + # Check toolchain ISA level if enabled mips64; then - enabled mips64r6 && check_inline_asm_flags mips64r6 '"dlsa $0, $0, $0, 1"' '-mips64r6' - enabled mips64r2 && check_inline_asm_flags mips64r2 '"dext $0, $0, 0, 1"' '-mips64r2' - disabled mips64r6 && disabled mips64r2 && check_inline_asm_flags mips64r1 '"daddi $0, $0, 0"' '-mips64' + enabled mips64r6 && check_inline_asm mips64r6 '"dlsa $0, $0, $0, 1"' && + disable mips64r2 + + enabled mips64r2 && check_inline_asm mips64r2 '"dext $0, $0, 0, 1"' + + disable mips32r6 && disable mips32r5 && disable mips32r2 else - enabled mips32r6 && check_inline_asm_flags mips32r6 '"aui $0, $0, 0"' '-mips32r6' - enabled mips32r5 && check_inline_asm_flags mips32r5 '"eretnc"' '-mips32r5' - enabled mips32r2 && check_inline_asm_flags mips32r2 '"ext $0, $0, 0, 1"' '-mips32r2' - disabled mips32r6 && disabled mips32r5 && disabled mips32r2 && check_inline_asm_flags mips32r1 '"addi $0, $0, 0"' '-mips32' + enabled mips32r6 && check_inline_asm mips32r6 '"aui $0, $0, 0"' && + disable mips32r5 && disable mips32r2 + + enabled mips32r5 && check_inline_asm mips32r5 '"eretnc"' + enabled mips32r2 && check_inline_asm mips32r2 '"ext $0, $0, 0, 1"' + + disable mips64r6 && disable mips64r5 && disable mips64r2 fi - enabled mipsfpu && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f2"' '-mhard-float' + enabled mipsfpu && check_inline_asm mipsfpu '"cvt.d.l $f0, $f2"' enabled mipsfpu && (enabled mips32r5 || enabled mips32r6 || enabled mips64r6) && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f1"' '-mfp64' - enabled mipsfpu && enabled msa && check_inline_asm_flags msa '"addvi.b $w0, $w1, 1"' '-mmsa' && check_headers msa.h || disable msa + enabled mipsdsp && check_inline_asm_flags mipsdsp '"addu.qb $t0, $t1, $t2"' '-mdsp' enabled mipsdspr2 && check_inline_asm_flags mipsdspr2 '"absq_s.qb $t0, $t1"' '-mdspr2' - enabled msa && enabled msa2 && check_inline_asm_flags msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && check_headers msa2.h || disable msa2 + + # MSA and MSA2 can be detected at runtime so we supply extra flags here + enabled mipsfpu && enabled msa && check_inline_asm msa '"addvi.b $w0, $w1, 1"' '-mmsa' && append MSAFLAGS '-mmsa' + enabled msa && enabled msa2 && check_inline_asm msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && append MSAFLAGS '-mmsa2' + + # loongson2 have no switch cflag so we can only probe toolchain ability + enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"' && disable loongson3 + + # loongson3 is paired with MMI + enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext' && append MMIFLAGS '-mloongson-ext' + + # MMI can be detected at runtime too + enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"' '-mloongson-mmi' && append MMIFLAGS '-mloongson-mmi' if enabled bigendian && enabled msa; then disable msa @@ -5898,10 +6037,10 @@ EOF elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" - check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" - check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" - check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" + enabled avx512 && check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" + enabled avx2 && check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" + enabled xop && check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" + enabled fma4 && check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" check_x86asm cpunop "CPU amdnop" fi @@ -6011,14 +6150,17 @@ check_func_headers mach/mach_time.h mach_absolute_time check_func_headers stdlib.h getenv check_func_headers sys/stat.h lstat +check_func_headers windows.h GetModuleHandle check_func_headers windows.h GetProcessAffinityMask check_func_headers windows.h GetProcessTimes +check_func_headers windows.h GetStdHandle check_func_headers windows.h GetSystemTimeAsFileTime check_func_headers windows.h LoadLibrary check_func_headers windows.h MapViewOfFile check_func_headers windows.h PeekNamedPipe check_func_headers windows.h SetConsoleTextAttribute check_func_headers windows.h SetConsoleCtrlHandler +check_func_headers windows.h SetDllDirectory check_func_headers windows.h Sleep check_func_headers windows.h VirtualAlloc check_func_headers glob.h glob @@ -6031,9 +6173,13 @@ check_headers dxgidebug.h check_headers dxva.h check_headers dxva2api.h -D_WIN32_WINNT=0x0600 check_headers io.h +enabled libdrm && + check_headers linux/dma-buf.h + check_headers linux/perf_event.h check_headers libcrystalhd/libcrystalhd_if.h check_headers malloc.h +check_headers mftransform.h check_headers net/udplite.h check_headers poll.h check_headers sys/param.h @@ -6074,6 +6220,7 @@ enabled videotoolbox && check_apple_framework VideoToolbox check_apple_framework CoreFoundation check_apple_framework CoreMedia check_apple_framework CoreVideo +check_apple_framework CoreAudio enabled avfoundation && { disable coregraphics applicationservices @@ -6083,6 +6230,7 @@ enabled avfoundation && { enabled videotoolbox && { check_lib coreservices CoreServices/CoreServices.h UTGetOSTypeFromString "-framework CoreServices" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2100_HLG "-framework CoreVideo" @@ -6091,13 +6239,16 @@ enabled videotoolbox && { check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss +check_type "windows.h dxva.h" "DXVA_PicParams_AV1" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h dxva.h" "DXVA_PicParams_HEVC" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h dxva.h" "DXVA_PicParams_VP9" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 +check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" +check_type "vdpau/vdpau.h" "VdpPictureInfoVP9" if [ -z "$nvccflags" ]; then nvccflags=$nvccflags_default @@ -6112,16 +6263,16 @@ fi if enabled cuda_nvcc; then nvccflags="$nvccflags -ptx" else - nvccflags="$nvccflags -S -nocudalib -nocudainc --cuda-device-only -include ${source_link}/compat/cuda/cuda_runtime.h" + nvccflags="$nvccflags -S -nocudalib -nocudainc --cuda-device-only -Wno-c++11-narrowing -include ${source_link}/compat/cuda/cuda_runtime.h" check_nvcc cuda_llvm fi if ! disabled ffnvcodec; then ffnv_hdr_list="ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h" - check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.0" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.8 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.9 ffnvcodec < 8.2" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.0.14.9 ffnvcodec < 8.1" "$ffnv_hdr_list" "" + check_pkg_config ffnvcodec "ffnvcodec >= 9.1.23.1" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.3 ffnvcodec < 9.1" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.10 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" "" fi check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" @@ -6191,10 +6342,11 @@ for func in $COMPLEX_FUNCS; do done # these are off by default, so fail if requested and not available +enabled avisynth && require_headers "avisynth/avisynth_c.h" enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; } enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled decklink && { require_headers DeckLinkAPI.h && - { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a090500" || die "ERROR: Decklink API version must be >= 10.9.5."; } } + { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a0a0000" || die "ERROR: Decklink API version must be >= 10.10"; } } enabled frei0r && require_headers "frei0r.h dlfcn.h" enabled gmp && require gmp gmp.h mpz_export -lgmp enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init @@ -6214,7 +6366,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 -enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.4.0" "dav1d/dav1d.h" dav1d_version +enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion @@ -6227,6 +6379,7 @@ enabled fontconfig && enable libfontconfig enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info +enabled libglslang && require_cpp libglslang glslang/SPIRV/GlslangToSpv.h "glslang::TIntermediate*" -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || require libgme gme/gme.h gme_new_emu -lgme -lstdc++; } enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do @@ -6244,10 +6397,14 @@ enabled liblensfun && require_pkg_config liblensfun lensfun lensfun.h lf_ # can find the libraries and headers through other means. enabled libmfx && { check_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit || { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } } +if enabled libmfx; then + check_cc MFX_CODEC_VP9 "mfx/mfxvp9.h mfx/mfxstructures.h" "MFX_CODEC_VP9" +fi + enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs -enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_load || - require libmysofa mysofa.h mysofa_load -lmysofa $zlib_extralibs; } +enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine || + require libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine -lmysofa $zlib_extralibs; } enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc -lnppidei || check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc -lnppidei || die "ERROR: libnpp not found"; } @@ -6261,6 +6418,7 @@ enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_ enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" +enabled libopenvino && require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api enabled libopus && { enabled libopus_decoder && { require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create @@ -6270,6 +6428,9 @@ enabled libopus && { } } enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new +enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection +enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new +enabled librist && require_pkg_config librist "librist >= 0.2" librist/librist.h rist_receiver_create enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++" @@ -6281,6 +6442,7 @@ enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp_init enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket +enabled libsvtav1 && require_pkg_config libsvtav1 "SvtAv1Enc >= 0.8.4" EbSvtAv1Enc.h svt_av1_enc_init_handle enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg @@ -6288,9 +6450,10 @@ enabled libtls && require_pkg_config libtls libtls tls.h tls_configur enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit -enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init @@ -6317,7 +6480,6 @@ enabled libvpx && { fi } -enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack enabled libwebp && { enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; } @@ -6327,12 +6489,12 @@ enabled libx264 && { check_pkg_config libx264 x264 "stdint.h x264.h" x require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && check_cpp_condition libx262 x264.h "X264_MPEG2" enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && - require_cpp_condition libx265 x265.h "X265_BUILD >= 68" + require_cpp_condition libx265 x265.h "X265_BUILD >= 70" enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxavs2 && require_pkg_config libxavs2 "xavs2 >= 1.3.0" "stdint.h xavs2.h" xavs2_api_get enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libzimg && require_pkg_config libzimg "zimg >= 2.7.0" zimg.h zimg_get_api_version -enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new +enabled libzmq && require_pkg_config libzmq "libzmq >= 4.2.1" zmq.h zmq_ctx_new enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && { test_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; } @@ -6367,12 +6529,16 @@ enabled opengl && { check_lib opengl GL/glx.h glXGetProcAddress "-lGL check_lib opengl ES2/gl.h glGetError "-isysroot=${sysroot} -Wl,-framework,OpenGLES" || die "ERROR: opengl not found." } +enabled omx_rpi && { test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame || + { ! enabled cross_compile && + add_cflags -isystem/opt/vc/include/IL && + test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame; } || + die "ERROR: OpenMAX IL headers from raspberrypi/firmware not found"; } && + enable omx enabled omx && require_headers OMX_Core.h -enabled omx_rpi && { check_headers OMX_Core.h || - { ! enabled cross_compile && add_cflags -isystem/opt/vc/include/IL && check_headers OMX_Core.h ; } || - die "ERROR: OpenMAX IL headers not found"; } && enable omx enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl || check_pkg_config openssl openssl openssl/ssl.h SSL_library_init || + check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || @@ -6448,19 +6614,21 @@ pod2man --help > /dev/null 2>&1 && enable pod2man || disable pod2man rsync --help 2> /dev/null | grep -q 'contimeout' && enable rsync_contimeout || disable rsync_contimeout # check V4L2 codecs available in the API -check_headers linux/fb.h -check_headers linux/videodev2.h -test_code cc linux/videodev2.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete -check_cc v4l2_m2m linux/videodev2.h "int i = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_BUF_FLAG_LAST;" -check_cc vc1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VC1_ANNEX_G;" -check_cc mpeg1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG1;" -check_cc mpeg2_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2;" -check_cc mpeg4_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG4;" -check_cc hevc_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC;" -check_cc h263_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H263;" -check_cc h264_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H264;" -check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;" -check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" +if enabled v4l2_m2m; then + check_headers linux/fb.h + check_headers linux/videodev2.h + test_code cc linux/videodev2.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete + check_cc v4l2_m2m linux/videodev2.h "int i = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_BUF_FLAG_LAST;" + check_cc vc1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VC1_ANNEX_G;" + check_cc mpeg1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG1;" + check_cc mpeg2_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2;" + check_cc mpeg4_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG4;" + check_cc hevc_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC;" + check_cc h263_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H263;" + check_cc h264_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H264;" + check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;" + check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" +fi check_headers sys/videoio.h test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete @@ -6488,8 +6656,8 @@ else EOF fi -enabled alsa && check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || - check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound +enabled alsa && { check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || + check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound; } enabled libjack && require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range @@ -6530,6 +6698,9 @@ test_cpp <= 0.35.0" "va/va.h" vaInitialize @@ -6544,6 +6715,8 @@ if enabled vaapi; then check_type "va/va.h va/va_dec_hevc.h" "VAPictureParameterBufferHEVC" check_struct "va/va.h" "VADecPictureParameterBufferVP9" bit_depth + check_struct "va/va.h" "VADecPictureParameterBufferAV1" bit_depth_idx + check_type "va/va.h va/va_vpp.h" "VAProcFilterParameterBufferHDRToneMapping" check_struct "va/va.h va/va_vpp.h" "VAProcPipelineCaps" rotation_flags check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC" check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG" @@ -6585,6 +6758,9 @@ enabled vdpau && enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd +enabled vulkan && + require_pkg_config vulkan "vulkan >= 1.1.97" "vulkan/vulkan.h" vkCreateInstance + if enabled x86; then case $target_os in mingw32*|mingw64*|win32|win64|linux|cygwin*) @@ -6593,7 +6769,7 @@ if enabled x86; then disable ffnvcodec cuvid nvdec nvenc ;; esac -elif enabled ppc64 && ! enabled bigendian; then +elif enabled_any aarch64 ppc64 && ! enabled bigendian; then case $target_os in linux) ;; @@ -6615,9 +6791,13 @@ void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } }; int main(void) { return 0; } EOF +if enabled_any nvdec cuvid; then + check_type "ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h" "CUVIDAV1PICPARAMS" +fi + enabled amf && check_cpp_condition amf "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400090000" # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then @@ -7335,7 +7515,6 @@ LD_LIB=$LD_LIB LD_PATH=$LD_PATH DLLTOOL=$dlltool WINDRES=$windres -DEPWINDRES=$dep_cc DOXYGEN=$doxygen LDFLAGS=$LDFLAGS LDEXEFLAGS=$LDEXEFLAGS @@ -7343,6 +7522,8 @@ LDSOFLAGS=$LDSOFLAGS SHFLAGS=$(echo $($ldflags_filter $SHFLAGS)) ASMSTRIPFLAGS=$ASMSTRIPFLAGS X86ASMFLAGS=$X86ASMFLAGS +MSAFLAGS=$MSAFLAGS +MMIFLAGS=$MMIFLAGS BUILDSUF=$build_suffix PROGSSUF=$progs_suffix FULLNAME=$FULLNAME @@ -7416,10 +7597,11 @@ cat > $TMPH < Date: Thu, 19 Aug 2021 16:43:30 -0400 Subject: [PATCH 06/11] Fix dts assetion --- libavformat/movenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 1bf8a2e7a43a9..9e9d48bfea2c9 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -5539,7 +5539,7 @@ static int mov_auto_flush_fragment(AVFormatContext *s, int force) return ret; } -#define DTS_THRESHOLD 1 +#define DTS_THRESHOLD 0 static int check_pkt(AVFormatContext *s, AVPacket *pkt) { From 1a893ded7543df5310de5ec16a477e6f01724389 Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Thu, 23 Sep 2021 22:00:37 -0400 Subject: [PATCH 07/11] Fix a crash when releasing aes mem --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index fd5311c34bbe8..8bf0b096cef88 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -744,6 +744,7 @@ static void dash_free(AVFormatContext *s) else avio_close(os->ctx->pb); } + aes_free(os); ff_format_io_close(s, &os->out); avformat_free_context(os->ctx); avcodec_free_context(&os->parser_avctx); @@ -754,7 +755,6 @@ static void dash_free(AVFormatContext *s) av_freep(&os->single_file_name); av_freep(&os->init_seg_name); av_freep(&os->media_seg_name); - aes_free(os); } av_freep(&c->streams); From 44e6452cf04b28869cfe84fce5a5325fb7e06456 Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Mon, 27 Sep 2021 21:21:34 -0400 Subject: [PATCH 08/11] Use another approach for fixing the crash --- libavformat/dashenc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 8bf0b096cef88..73163f09d4d9c 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -281,7 +281,8 @@ static void aes_free(OutputStream *os) { memset(&os->aes_pad[os->aes_pad_len], pad, pad); av_aes_crypt(os->aes_context, out_buf, os->aes_pad, 1, os->aes_iv, 0); - avio_write(os->out, out_buf, BLOCKSIZE); + if (os->out) + avio_write(os->out, out_buf, BLOCKSIZE); } av_freep(&os->aes_context); av_freep(&os->aes_write_buf); @@ -744,7 +745,6 @@ static void dash_free(AVFormatContext *s) else avio_close(os->ctx->pb); } - aes_free(os); ff_format_io_close(s, &os->out); avformat_free_context(os->ctx); avcodec_free_context(&os->parser_avctx); @@ -755,6 +755,7 @@ static void dash_free(AVFormatContext *s) av_freep(&os->single_file_name); av_freep(&os->init_seg_name); av_freep(&os->media_seg_name); + aes_free(os); } av_freep(&c->streams); From 5ad818b138ac72cbf4d2c0b35f65be47f73f9cfc Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Fri, 8 Oct 2021 17:15:59 -0400 Subject: [PATCH 09/11] Fix a crash in cuda library when cuvid_decode_init() fails --- libavcodec/cuviddec.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 5c135d17144bb..4c80f4731d702 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -682,13 +682,15 @@ static int cuvid_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, static av_cold int cuvid_decode_end(AVCodecContext *avctx) { CuvidContext *ctx = avctx->priv_data; - AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)ctx->hwdevice->data; - AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; - CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; - av_fifo_freep(&ctx->frame_queue); - ctx->cudl->cuCtxPushCurrent(cuda_ctx); + if (ctx->hwdevice) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)ctx->hwdevice->data; + AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; + CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; + + ctx->cudl->cuCtxPushCurrent(cuda_ctx); + } if (ctx->cuparser) ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser); From 2371d69c6f90d7b7a11bfafdb02b48c715801b91 Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Fri, 8 Oct 2021 17:43:32 -0400 Subject: [PATCH 10/11] Fix a compile error --- libavcodec/cuviddec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 4c80f4731d702..d314c9c97be0a 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -682,12 +682,13 @@ static int cuvid_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, static av_cold int cuvid_decode_end(AVCodecContext *avctx) { CuvidContext *ctx = avctx->priv_data; + CUcontext dummy; av_fifo_freep(&ctx->frame_queue); if (ctx->hwdevice) { AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)ctx->hwdevice->data; AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; - CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; + CUcontext cuda_ctx = device_hwctx->cuda_ctx; ctx->cudl->cuCtxPushCurrent(cuda_ctx); } From 88f5cf6cca3b28ae63b21ff5657c3a0ade94a6d4 Mon Sep 17 00:00:00 2001 From: Reza mIr Date: Mon, 11 Oct 2021 10:53:42 -0400 Subject: [PATCH 11/11] check for cudl NULL value --- libavcodec/cuviddec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index d314c9c97be0a..3a7fde4826a0e 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -699,7 +699,8 @@ static av_cold int cuvid_decode_end(AVCodecContext *avctx) if (ctx->cudecoder) ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder); - ctx->cudl->cuCtxPopCurrent(&dummy); + if (ctx->cudl) + ctx->cudl->cuCtxPopCurrent(&dummy); ctx->cudl = NULL;