mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-05-13 21:26:33 +02:00
avcodec/hevc/ps: Add basic HEVC_SCALABILITY_AUXILIARY support
Only implementing what's needed for HEVC with alpha. Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
This commit is contained in:
parent
d3220ed818
commit
d367016d3c
@ -170,4 +170,9 @@ enum HEVCScalabilityMask {
|
|||||||
HEVC_SCALABILITY_MASK_MAX = 0xFFFF,
|
HEVC_SCALABILITY_MASK_MAX = 0xFFFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum HEVCAuxId {
|
||||||
|
HEVC_AUX_ALPHA = 1,
|
||||||
|
HEVC_AUX_DEPTH = 2,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* AVCODEC_HEVC_HEVC_H */
|
#endif /* AVCODEC_HEVC_HEVC_H */
|
||||||
|
@ -460,14 +460,17 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
uint64_t layer1_id_included)
|
uint64_t layer1_id_included)
|
||||||
{
|
{
|
||||||
PTL ptl_dummy;
|
PTL ptl_dummy;
|
||||||
uint8_t max_sub_layers[HEVC_MAX_LAYERS];
|
uint8_t max_sub_layers[HEVC_MAX_LAYERS] = {1, 1};
|
||||||
|
uint8_t dimension_id_len[16] = {0};
|
||||||
|
uint8_t dimension_id[16] = {0};
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
int splitting_flag, dimension_id_len, view_id_len, num_add_olss, num_scalability_types,
|
int splitting_flag, view_id_len, num_add_olss, num_scalability_types,
|
||||||
default_output_layer_idc, direct_dep_type_len, direct_dep_type,
|
default_output_layer_idc, direct_dep_type_len, direct_dep_type,
|
||||||
sub_layers_max_present, sub_layer_flag_info_present_flag, nb_ptl;
|
sub_layers_max_present, sub_layer_flag_info_present_flag, nb_ptl;
|
||||||
unsigned non_vui_extension_length;
|
unsigned non_vui_extension_length;
|
||||||
|
|
||||||
if (vps->vps_max_layers == 1 || vps->vps_num_layer_sets == 1) {
|
if (vps->vps_max_layers == 1) {
|
||||||
av_log(avctx, AV_LOG_VERBOSE, "Ignoring VPS extensions with a single layer\n");
|
av_log(avctx, AV_LOG_VERBOSE, "Ignoring VPS extensions with a single layer\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -520,6 +523,7 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
*/
|
*/
|
||||||
vps->nb_layers = 2;
|
vps->nb_layers = 2;
|
||||||
|
|
||||||
|
/* vps_base_layer_internal_flag is true has been checked before */
|
||||||
if (parse_ptl(gb, avctx, 0, &ptl_dummy, vps->vps_max_sub_layers) < 0)
|
if (parse_ptl(gb, avctx, 0, &ptl_dummy, vps->vps_max_sub_layers) < 0)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
@ -529,20 +533,25 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
if (!num_scalability_types) {
|
if (!num_scalability_types) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Missing scalability mask\n");
|
av_log(avctx, AV_LOG_ERROR, "Missing scalability mask\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
} else if (num_scalability_types > 1) {
|
|
||||||
av_log(avctx, AV_LOG_ERROR, "Scalability number %d not supported\n",
|
|
||||||
num_scalability_types);
|
|
||||||
return AVERROR_PATCHWELCOME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW)) {
|
if (!(vps->scalability_mask_flag &
|
||||||
|
(HEVC_SCALABILITY_MULTIVIEW | HEVC_SCALABILITY_AUXILIARY))) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Scalability type %d not supported\n",
|
av_log(avctx, AV_LOG_ERROR, "Scalability type %d not supported\n",
|
||||||
15 - ff_ctz(vps->scalability_mask_flag));
|
15 - ff_ctz(vps->scalability_mask_flag));
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
|
// x265 specify MULTIVIEW when the stream really is alpha video only.
|
||||||
|
if (num_scalability_types > 1)
|
||||||
|
av_log(avctx, AV_LOG_WARNING, "Multiple scalability types presented\n");
|
||||||
|
|
||||||
if (!splitting_flag)
|
n = 0;
|
||||||
dimension_id_len = get_bits(gb, 3) + 1;
|
for (int i = 0; i < num_scalability_types - splitting_flag; i++) {
|
||||||
|
dimension_id_len[i] = get_bits(gb, 3) + 1;
|
||||||
|
n += dimension_id_len[i];
|
||||||
|
}
|
||||||
|
if (splitting_flag)
|
||||||
|
dimension_id_len[num_scalability_types - 1] = 5 - n;
|
||||||
|
|
||||||
if (get_bits1(gb)) { /* vps_nuh_layer_id_present_flag */
|
if (get_bits1(gb)) { /* vps_nuh_layer_id_present_flag */
|
||||||
int layer_id_in_nuh = get_bits(gb, 6);
|
int layer_id_in_nuh = get_bits(gb, 6);
|
||||||
@ -559,28 +568,57 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!splitting_flag) {
|
if (!splitting_flag) {
|
||||||
int view_idx = get_bits(gb, dimension_id_len);
|
int index = 0;
|
||||||
if (view_idx != 1) {
|
|
||||||
av_log(avctx, AV_LOG_ERROR, "Unexpected ViewOrderIdx: %d\n", view_idx);
|
for (int i = 0; i < num_scalability_types; i++)
|
||||||
|
dimension_id[i] = get_bits(gb, dimension_id_len[i]);
|
||||||
|
|
||||||
|
if (vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW)
|
||||||
|
index++;
|
||||||
|
|
||||||
|
/* AuxId 1 is alpha, 2 is depth. Only support alpha */
|
||||||
|
if (vps->scalability_mask_flag & HEVC_SCALABILITY_AUXILIARY &&
|
||||||
|
dimension_id[index] != HEVC_AUX_ALPHA) {
|
||||||
|
av_log(avctx, AV_LOG_WARNING,
|
||||||
|
"Unsupported dimension_id %d for HEVC_SCALABILITY_AUXILIARY\n",
|
||||||
|
dimension_id[index]);
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view_id_len = get_bits(gb, 4);
|
view_id_len = get_bits(gb, 4);
|
||||||
if (view_id_len)
|
if (view_id_len) {
|
||||||
for (int i = 0; i < 2 /* NumViews */; i++)
|
n = (vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW) ? 2 : 1;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
vps->view_id[i] = get_bits(gb, view_id_len);
|
vps->view_id[i] = get_bits(gb, view_id_len);
|
||||||
|
}
|
||||||
|
|
||||||
if (!get_bits1(gb) /* direct_dependency_flag */) {
|
/* direct_dependency_flag */
|
||||||
av_log(avctx, AV_LOG_WARNING, "Independent output layers not supported\n");
|
vps->num_direct_ref_layers[1] = get_bits1(gb);
|
||||||
|
if (!vps->num_direct_ref_layers[1]) {
|
||||||
|
vps->num_add_layer_sets = get_ue_golomb(gb);
|
||||||
|
if (vps->num_add_layer_sets > 1) {
|
||||||
|
av_log(avctx, AV_LOG_WARNING,
|
||||||
|
"Unsupported num_add_layer_sets: %d\n", vps->num_add_layer_sets);
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
vps->num_direct_ref_layers[1] = 1;
|
|
||||||
|
if (vps->num_add_layer_sets) {
|
||||||
|
/* highest_layer_idx_plus1 */
|
||||||
|
if (!get_bits1(gb))
|
||||||
|
return AVERROR_PATCHWELCOME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vps->num_output_layer_sets = vps->vps_num_layer_sets + vps->num_add_layer_sets;
|
||||||
|
if (vps->num_output_layer_sets != 2)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
sub_layers_max_present = get_bits1(gb); // vps_sub_layers_max_minus1_present_flag
|
sub_layers_max_present = get_bits1(gb); // vps_sub_layers_max_minus1_present_flag
|
||||||
|
if (sub_layers_max_present) {
|
||||||
for (int i = 0; i < vps->vps_max_layers; i++)
|
for (int i = 0; i < vps->vps_max_layers; i++)
|
||||||
max_sub_layers[i] = sub_layers_max_present ? get_bits(gb, 3) + 1 :
|
max_sub_layers[i] = sub_layers_max_present ? get_bits(gb, 3) + 1 :
|
||||||
vps->vps_max_sub_layers;
|
vps->vps_max_sub_layers;
|
||||||
|
}
|
||||||
|
|
||||||
if (get_bits1(gb) /* max_tid_ref_present_flag */)
|
if (get_bits1(gb) /* max_tid_ref_present_flag */)
|
||||||
skip_bits(gb, 3); // max_tid_il_ref_pics_plus1
|
skip_bits(gb, 3); // max_tid_il_ref_pics_plus1
|
||||||
@ -613,18 +651,24 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Consequence of established layer dependencies */
|
/* Consequence of established layer dependencies */
|
||||||
if (layer1_id_included != ((1 << vps->layer_id_in_nuh[0]) |
|
if (layer1_id_included &&
|
||||||
|
layer1_id_included != ((1 << vps->layer_id_in_nuh[0]) |
|
||||||
(1 << vps->layer_id_in_nuh[1]))) {
|
(1 << vps->layer_id_in_nuh[1]))) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Dependent layer not included in layer ID?\n");
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
|
"Dependent layer not included in layer ID?\n");
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
|
if (!layer1_id_included)
|
||||||
vps->num_output_layer_sets = 2;
|
vps->ols[1] = 2;
|
||||||
|
else
|
||||||
vps->ols[1] = 3;
|
vps->ols[1] = 3;
|
||||||
|
|
||||||
|
if (vps->vps_num_layer_sets == 1 || default_output_layer_idc == 2)
|
||||||
|
skip_bits1(gb);
|
||||||
|
|
||||||
for (int j = 0; j < av_popcount64(vps->ols[1]); j++) {
|
for (int j = 0; j < av_popcount64(vps->ols[1]); j++) {
|
||||||
int ptl_idx = get_bits(gb, av_ceil_log2(nb_ptl));
|
int ptl_idx = get_bits(gb, av_ceil_log2(nb_ptl));
|
||||||
if (ptl_idx < 1 || ptl_idx >= nb_ptl) {
|
if (ptl_idx >= nb_ptl) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Invalid PTL index: %d\n", ptl_idx);
|
av_log(avctx, AV_LOG_ERROR, "Invalid PTL index: %d\n", ptl_idx);
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -667,6 +711,8 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
|
|
||||||
vps->max_one_active_ref_layer = get_bits1(gb);
|
vps->max_one_active_ref_layer = get_bits1(gb);
|
||||||
vps->poc_lsb_aligned = get_bits1(gb);
|
vps->poc_lsb_aligned = get_bits1(gb);
|
||||||
|
if (!vps->num_direct_ref_layers[1])
|
||||||
|
vps->poc_lsb_not_present = get_bits1(gb) << 1;
|
||||||
|
|
||||||
sub_layer_flag_info_present_flag = get_bits1(gb);
|
sub_layer_flag_info_present_flag = get_bits1(gb);
|
||||||
for (int j = 0; j < FFMAX(max_sub_layers[0], max_sub_layers[1]); j++) {
|
for (int j = 0; j < FFMAX(max_sub_layers[0], max_sub_layers[1]); j++) {
|
||||||
@ -688,13 +734,15 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_bits1(gb); /* direct_depenency_all_layers_flag */
|
/* direct_depenency_all_layers_flag */
|
||||||
|
if (get_bits1(gb)) {
|
||||||
direct_dep_type = get_bits_long(gb, direct_dep_type_len);
|
direct_dep_type = get_bits_long(gb, direct_dep_type_len);
|
||||||
if (direct_dep_type > HEVC_DEP_TYPE_BOTH) {
|
if (direct_dep_type > HEVC_DEP_TYPE_BOTH) {
|
||||||
av_log(avctx, AV_LOG_WARNING, "Unsupported direct_dep_type: %d\n",
|
av_log(avctx, AV_LOG_WARNING, "Unsupported direct_dep_type: %d\n",
|
||||||
direct_dep_type);
|
direct_dep_type);
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
non_vui_extension_length = get_ue_golomb(gb);
|
non_vui_extension_length = get_ue_golomb(gb);
|
||||||
if (non_vui_extension_length > 4096) {
|
if (non_vui_extension_length > 4096) {
|
||||||
@ -718,6 +766,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx,
|
|||||||
ptrdiff_t nal_size = gb->buffer_end - gb->buffer;
|
ptrdiff_t nal_size = gb->buffer_end - gb->buffer;
|
||||||
int ret = AVERROR_INVALIDDATA;
|
int ret = AVERROR_INVALIDDATA;
|
||||||
uint64_t layer1_id_included = 0;
|
uint64_t layer1_id_included = 0;
|
||||||
|
unsigned vps_base_layer_internal_flag, vps_base_layer_available_flag;
|
||||||
HEVCVPS *vps;
|
HEVCVPS *vps;
|
||||||
|
|
||||||
if (ps->vps_list[vps_id]) {
|
if (ps->vps_list[vps_id]) {
|
||||||
@ -741,8 +790,12 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx,
|
|||||||
}
|
}
|
||||||
vps->vps_id = vps_id;
|
vps->vps_id = vps_id;
|
||||||
|
|
||||||
if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits
|
vps_base_layer_internal_flag = get_bits1(gb);
|
||||||
av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n");
|
vps_base_layer_available_flag = get_bits1(gb);
|
||||||
|
if (!vps_base_layer_internal_flag || !vps_base_layer_available_flag) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
|
"vps_base_layer_internal_flag or vps_base_layer_available_flag not set\n");
|
||||||
|
ret = AVERROR_PATCHWELCOME;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +237,7 @@ typedef struct HEVCVPS {
|
|||||||
|
|
||||||
// NumDirectRefLayers[layer_idx]
|
// NumDirectRefLayers[layer_idx]
|
||||||
uint8_t num_direct_ref_layers[HEVC_VPS_MAX_LAYERS];
|
uint8_t num_direct_ref_layers[HEVC_VPS_MAX_LAYERS];
|
||||||
|
uint8_t num_add_layer_sets;
|
||||||
|
|
||||||
RepFormat rep_format;
|
RepFormat rep_format;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user