mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-10-28 10:04:37 +08:00
avcodec/hevc: fill the stream parameters when all frames are skipped
With skip_frame at AVDISCARD_ALL the parameter set and SEI NAL units are still decoded, and as long as no decoded frame has configured the decoder, the parameters of the SPS activated by the first slice are exported. Declaring FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM on top of that lets avformat_find_stream_info() fill the stream parameters without decoding any frame: ┌─────────────────────────────────────────┬───────────┬───────────┬──────────────────────┐ │ sample │ master │ skipframe │ │ ├─────────────────────────────────────────┼───────────┼───────────┼──────────────────────┤ │ loewe.ts (hevc/TS) │ 17.2 ±1.0 │ 4.8 ±0.5 │ 3.56× (p=2e-71) │ ├─────────────────────────────────────────┼───────────┼───────────┼──────────────────────┤ │ DELTAQP_A_BRCM_4.bit │ 21.7 ±0.7 │ 10.6 ±0.3 │ 2.05× (p=3e-78) │ ├─────────────────────────────────────────┼───────────┼───────────┼──────────────────────┤ │ hevc/paramchange │ 59.8 ±1.7 │ 4.3 ±0.3 │ 13.93× (p=2e-79) │ └─────────────────────────────────────────┴───────────┴───────────┴──────────────────────┘
This commit is contained in:
1 parent
3369578ba4
commit
7ac9cb4340
1 file changed
+59
-2
@@ -3733,10 +3733,47 @@ static void decode_reset_recovery_point(HEVCContext *s)
|
||||
s->sei.recovery_point.has_recovery_poc = 0;
|
||||
}
|
||||
|
||||
static int export_stream_params_from_slice(HEVCContext *s, const H2645NAL *nal)
|
||||
{
|
||||
GetBitContext gb = nal->gb;
|
||||
const HEVCSPS *sps;
|
||||
const HEVCVPS *vps;
|
||||
unsigned pps_id;
|
||||
|
||||
int is_slice = nal->type <= HEVC_NAL_RASL_R ||
|
||||
(nal->type >= HEVC_NAL_BLA_W_LP &&
|
||||
nal->type <= HEVC_NAL_CRA_NUT);
|
||||
|
||||
if (!is_slice || nal->nuh_layer_id)
|
||||
return 0;
|
||||
|
||||
skip_bits1(&gb); // first_slice_segment_in_pic_flag
|
||||
if (nal->type >= HEVC_NAL_BLA_W_LP)
|
||||
skip_bits1(&gb); // no_output_of_prior_pics_flag
|
||||
pps_id = get_ue_golomb_long(&gb);
|
||||
if (pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[pps_id])
|
||||
return 0;
|
||||
sps = s->ps.pps_list[pps_id]->sps;
|
||||
vps = sps->vps;
|
||||
|
||||
export_stream_params(s, sps);
|
||||
|
||||
if (vps->nb_layers == 2 && vps->layer_id_in_nuh[1] &&
|
||||
vps->scalability_mask_flag & HEVC_SCALABILITY_AUXILIARY) {
|
||||
enum AVPixelFormat alpha_fmt = map_to_alpha_format(s, sps->pix_fmt);
|
||||
|
||||
if (alpha_fmt != AV_PIX_FMT_NONE)
|
||||
s->avctx->pix_fmt = alpha_fmt;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
{
|
||||
int ret = 0;
|
||||
int eos_at_start = 1;
|
||||
int params_exported = 0;
|
||||
int flags = (H2645_FLAG_IS_NALFF * !!s->is_nalff) | H2645_FLAG_SMALL_PADDING;
|
||||
|
||||
s->cur_frame = s->collocated_ref = NULL;
|
||||
@@ -3818,8 +3855,21 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
for (int i = 0; i < s->pkt.nb_nals; i++) {
|
||||
H2645NAL *nal = &s->pkt.nals[i];
|
||||
|
||||
if (s->avctx->skip_frame >= AVDISCARD_ALL ||
|
||||
(s->avctx->skip_frame >= AVDISCARD_NONREF && ff_hevc_nal_is_nonref(nal->type)))
|
||||
if (s->avctx->skip_frame >= AVDISCARD_ALL) {
|
||||
switch (nal->type) {
|
||||
case HEVC_NAL_VPS:
|
||||
case HEVC_NAL_SPS:
|
||||
case HEVC_NAL_PPS:
|
||||
case HEVC_NAL_SEI_PREFIX:
|
||||
case HEVC_NAL_SEI_SUFFIX:
|
||||
break;
|
||||
default:
|
||||
if (!s->layers[0].sps && !params_exported)
|
||||
params_exported = export_stream_params_from_slice(s, nal);
|
||||
continue;
|
||||
}
|
||||
} else if (s->avctx->skip_frame >= AVDISCARD_NONREF &&
|
||||
ff_hevc_nal_is_nonref(nal->type))
|
||||
continue;
|
||||
|
||||
ret = decode_nal_unit(s, i);
|
||||
@@ -3830,6 +3880,12 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
|
||||
}
|
||||
}
|
||||
|
||||
if (params_exported) {
|
||||
ret = export_stream_params_from_sei(s);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {
|
||||
HEVCLayerContext *l = &s->layers[i];
|
||||
@@ -4300,6 +4356,7 @@ const FFCodec ff_hevc_decoder = {
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING |
|
||||
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM |
|
||||
FF_CODEC_CAP_USES_PROGRESSFRAMES |
|
||||
FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.p.profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles),
|
||||
|
||||
Reference in new issue
Block a user