avformat/hlsenc: support CODECS Attribute in hevc EXT-X-STREAM-INF

fix ticket: 8904
parse the SPS from extradata and get profile_tier_level
write the profile_tier_level info into CODECS Attribute

HLS CODECS Attribute reference to :https://developer.apple.com/documentation/http_live_streaming/hls_authoring_specification_for_apple_devices/hls_authoring_specification_for_apple_devices_appendixes

Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
Signed-off-by: liuqi05 <liuqi05@kuaishou.com>
pull/356/head
Steven Liu 4 years ago committed by liuqi05
parent b5ca8f2c66
commit a2b1dd0ce3
  1. 48
      libavformat/hlsenc.c

@ -46,6 +46,7 @@
#include "avformat.h"
#include "avio_internal.h"
#include "avc.h"
#if CONFIG_HTTP_PROTOCOL
#include "http.h"
#endif
@ -337,6 +338,49 @@ static void write_codec_attr(AVStream *st, VariantStream *vs)
} else {
goto fail;
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
uint8_t *data = st->codecpar->extradata;
int profile = FF_PROFILE_UNKNOWN;
int level = FF_LEVEL_UNKNOWN;
if (st->codecpar->profile != FF_PROFILE_UNKNOWN)
profile = st->codecpar->profile;
if (st->codecpar->level != FF_LEVEL_UNKNOWN)
level = st->codecpar->level;
/* check the boundary of data which from current position is small than extradata_size */
while (data && (data - st->codecpar->extradata + 5) < st->codecpar->extradata_size) {
/* get HEVC SPS NAL and seek to profile_tier_level */
if (!(data[0] | data[1] | data[2]) && data[3] == 1 && ((data[4] & 0x42) == 0x42)) {
int remain_size = 0;
int rbsp_size = 0;
/* skip start code + nalu header */
data += 6;
/* process by reference General NAL unit syntax */
remain_size = st->codecpar->extradata_size - (data - st->codecpar->extradata);
uint8_t *rbsp_buf = ff_nal_unit_extract_rbsp(data, remain_size, &rbsp_size, 0);
if (!rbsp_buf)
return;
if (rbsp_size < 13) {
av_freep(&rbsp_buf);
break;
}
/* skip sps_video_parameter_set_id u(4),
* sps_max_sub_layers_minus1 u(3),
* and sps_temporal_id_nesting_flag u(1) */
profile = rbsp_buf[1] & 0x1f;
/* skip 8 + 8 + 32 + 4 + 43 + 1 bit */
level = rbsp_buf[12];
av_freep(&rbsp_buf);
break;
}
data++;
}
if (st->codecpar->codec_tag == MKTAG('h','v','c','1') &&
profile != FF_PROFILE_UNKNOWN &&
level != FF_LEVEL_UNKNOWN) {
snprintf(attr, sizeof(attr), "%s.%d.4.L%d.B01", av_fourcc2str(st->codecpar->codec_tag), profile, level);
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
snprintf(attr, sizeof(attr), "mp4a.40.33");
} else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) {
@ -2247,6 +2291,10 @@ static int hls_write_header(AVFormatContext *s)
continue;
}
avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) {
av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n");
}
write_codec_attr(outer_st, vs);
}

Loading…
Cancel
Save