mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-24 08:12:44 +00:00
avformat/hlsenc: Add CODECS attribute to master playlist
This commit is contained in:
parent
381a4820c6
commit
0afa171f25
@ -820,7 +820,7 @@ static int write_manifest(AVFormatContext *s, int final)
|
||||
stream_bitrate += max_audio_bitrate;
|
||||
}
|
||||
get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
|
||||
ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup);
|
||||
ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL);
|
||||
}
|
||||
avio_close(out);
|
||||
if (use_rename)
|
||||
|
@ -58,6 +58,11 @@ typedef enum {
|
||||
HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2, // YYYYMMDDhhmmss
|
||||
} StartSequenceSourceType;
|
||||
|
||||
typedef enum {
|
||||
CODEC_ATTRIBUTE_WRITTEN = 0,
|
||||
CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN,
|
||||
} CodecAttributeStatus;
|
||||
|
||||
#define KEYSIZE 16
|
||||
#define LINE_BUFFER_SIZE 1024
|
||||
#define HLS_MICROSECOND_UNIT 1000000
|
||||
@ -142,6 +147,8 @@ typedef struct VariantStream {
|
||||
int fmp4_init_mode;
|
||||
|
||||
AVStream **streams;
|
||||
char codec_attr[128];
|
||||
CodecAttributeStatus attr_status;
|
||||
unsigned int nb_streams;
|
||||
int m3u8_created; /* status of media play-list creation */
|
||||
char *agroup; /* audio group name */
|
||||
@ -290,6 +297,51 @@ static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSCont
|
||||
|
||||
}
|
||||
|
||||
static void write_codec_attr(AVStream *st, VariantStream *vs) {
|
||||
int codec_strlen = strlen(vs->codec_attr);
|
||||
char attr[32];
|
||||
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
|
||||
return;
|
||||
if (vs->attr_status == CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN)
|
||||
return;
|
||||
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
|
||||
uint8_t *data = st->codecpar->extradata;
|
||||
if ((data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) {
|
||||
snprintf(attr, sizeof(attr),
|
||||
"avc1.%02x%02x%02x", data[5], data[6], data[7]);
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
} 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) {
|
||||
snprintf(attr, sizeof(attr), "mp4a.40.34");
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
|
||||
/* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 5 and 29 respectively */
|
||||
snprintf(attr, sizeof(attr), "mp4a.40.2");
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
|
||||
snprintf(attr, sizeof(attr), "ac-3");
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
|
||||
snprintf(attr, sizeof(attr), "ec-3");
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
// Don't write the same attribute multiple times
|
||||
if (!av_stristr(vs->codec_attr, attr)) {
|
||||
snprintf(vs->codec_attr + codec_strlen,
|
||||
sizeof(vs->codec_attr) - codec_strlen,
|
||||
"%s%s", codec_strlen ? "," : "", attr);
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
vs->codec_attr[0] = '\0';
|
||||
vs->attr_status = CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN;
|
||||
return;
|
||||
}
|
||||
|
||||
static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number)
|
||||
{
|
||||
const char *p;
|
||||
@ -1227,7 +1279,7 @@ static int create_master_playlist(AVFormatContext *s,
|
||||
bandwidth += bandwidth / 10;
|
||||
|
||||
ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
|
||||
aud_st ? vs->agroup : NULL);
|
||||
aud_st ? vs->agroup : NULL, vs->codec_attr);
|
||||
|
||||
av_freep(&m3u8_rel_name);
|
||||
}
|
||||
@ -1857,6 +1909,19 @@ 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);
|
||||
write_codec_attr(outer_st, vs);
|
||||
|
||||
}
|
||||
/* Update the Codec Attr string for the mapped audio groups */
|
||||
if (vs->has_video && vs->agroup) {
|
||||
for (j = 0; j < hls->nb_varstreams; j++) {
|
||||
VariantStream *vs_agroup = &(hls->var_streams[j]);
|
||||
if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
|
||||
vs_agroup->agroup &&
|
||||
!av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
|
||||
write_codec_attr(vs_agroup->streams[0], vs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail:
|
||||
|
@ -46,7 +46,8 @@ void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup,
|
||||
}
|
||||
|
||||
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
|
||||
int bandwidth, char *filename, char *agroup) {
|
||||
int bandwidth, char *filename, char *agroup,
|
||||
char *codecs) {
|
||||
if (!out || !filename)
|
||||
return;
|
||||
|
||||
@ -60,6 +61,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
|
||||
if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
|
||||
avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
|
||||
st->codecpar->height);
|
||||
if (codecs && strlen(codecs) > 0)
|
||||
avio_printf(out, ",CODECS=\"%s\"", codecs);
|
||||
if (agroup && strlen(agroup) > 0)
|
||||
avio_printf(out, ",AUDIO=\"group_%s\"", agroup);
|
||||
avio_printf(out, "\n%s\n\n", filename);
|
||||
|
@ -40,7 +40,8 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version);
|
||||
void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup,
|
||||
char *filename, int name_id, int is_default);
|
||||
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out,
|
||||
int bandwidth, char *filename, char *agroup);
|
||||
int bandwidth, char *filename, char *agroup,
|
||||
char *codecs);
|
||||
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache,
|
||||
int target_duration, int64_t sequence,
|
||||
uint32_t playlist_type);
|
||||
|
Loading…
Reference in New Issue
Block a user