From patchwork Sun Jul 14 15:16:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: CoderVenkat X-Patchwork-Id: 50532 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:2298:b0:482:c625:d099 with SMTP id fp24csp1832417vqb; Sun, 14 Jul 2024 08:41:46 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCXSCtoNlrqlalHb+/XIGez2xEHQ+tEF2QZdwjmlKl2rDNPsyk0pS242+KseQXDVneqSaPr3nca/BcEOXJ0p9xMOxFC7RO7a8KHmng== X-Google-Smtp-Source: AGHT+IEM/9dj/m+Rw9lxpf9mGnFR1uUO8uarnP2PyN3LmM89YELD8+6YQVhk1bzgSIess6kv667+ X-Received: by 2002:a17:906:493:b0:a77:eb34:3b42 with SMTP id a640c23a62f3a-a780b689212mr1160090366b.12.1720971706358; Sun, 14 Jul 2024 08:41:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1720971706; cv=none; d=google.com; s=arc-20160816; b=xw66cbOAA5jArukfpLK6QV532Odvwjv4PLvl+HBbiu+ODtmgfMyCm+zkE7h7Ozywg+ kBTaKUJwd/vK1rScIiImTZz9X9MO0kkJf51b62mkadWkKXeYTkDwswn0HxTbdcghpodN 313+s4vdrGTX3XHi8cTVRCdNxtOZt/nUE6VN7E2/Suf3++f2Tl5QEoJvtdP8j7q5xI+4 GLMGd9mq18iDNmnGXn/7ATPPjJgekG5DCiYCBbFE1ZK7pREVj5F0AhPEyVDq2NEDGGAI 4Mdu+PUaKtIF+MIQCdyvLOYWqbQc0cnxyyf/yVT/Lwai5FaJo4wYRM/D2tQg9i4By6xa fSOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :in-reply-to:from:content-language:references:to:user-agent :mime-version:date:message-id:dkim-signature:delivered-to; bh=zj6ncAAyRsc3JbphBks4mdol7/8utY4uam4+xopPez4=; fh=q41DpHH7g+pT9ijxQSS5qY0keDg6/hn5Sx933NqzhoE=; b=uKojEpeFEKJO1fmNBE6xqM19fCDvhnDpSHXjVcWM1ZTvB5gwWrpqjObBItpDn9nlaG k0H9esahJ0d7PsSK0PIQi6bkzOGqOdDF/Y+LWeYo5y1QW49SF+0c+rgsWa39erMcWhDf entpcMnvwrvdqbwpDuUo2S/xP33PTz5AZWyK9Rsv/4I61CUS2JnVnwDdz2FyOOyjhcU8 PEaMSXKaIVszW+T68wDIBHn9BMgV2LlivVaUg2wzkpG6mmEv5MbqumFjzCA8QOqJsMyU hVeZBm/pLUa/p6Dtc6VsD+TEjIXv9VjaDT20yxjXOHFkWsIzxGV4hB3ZF7q8URwPYPhP x0tg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b="RC/wNkBC"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a640c23a62f3a-a79bc82783esi161889566b.932.2024.07.14.08.41.45; Sun, 14 Jul 2024 08:41:46 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b="RC/wNkBC"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3576068D94D; Sun, 14 Jul 2024 18:16:39 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-io1-f51.google.com (mail-io1-f51.google.com [209.85.166.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C1BD868D92F for ; Sun, 14 Jul 2024 18:16:31 +0300 (EEST) Received: by mail-io1-f51.google.com with SMTP id ca18e2360f4ac-8076708e8ffso197067039f.0 for ; Sun, 14 Jul 2024 08:16:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720970190; x=1721574990; darn=ffmpeg.org; h=in-reply-to:from:cc:content-language:references:to:subject :user-agent:mime-version:date:message-id:from:to:cc:subject:date :message-id:reply-to; bh=uljPmtxYh7PnF+0oygZcBxrioPZKWd4FWs1iANqRjJ8=; b=RC/wNkBCwOlY3QMQ8Wu+aFmvmRHm5V35qhm0Xgt+fyglICp46Pix81djtomWixV1vl vcno1nq9+HSLF/uAfPhWJ+nnNWoTynOE/GGcrER1rzsN7A55cJWs3neRa2Vh5cbdVJeS 4X4zd6X/yJ/fVZx4LFLNc6soCUVjHudK68Nh4+aFpYjUBJaaJAjE92TsEnyUU1SqmxRn 9HBDkQrHS4Y5IvT10aXimAhmNToLmALVJh3X+eskU6XM0M4nyXKWZnEZ1Pv6RHFvzbc/ H/8rPj5YIN8ZLem3Tkob+KC/A4umm6khPKnsP95RmLPAT4vPE6fpl0Zph29RWJ+Bfy/u bQVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720970190; x=1721574990; h=in-reply-to:from:cc:content-language:references:to:subject :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=uljPmtxYh7PnF+0oygZcBxrioPZKWd4FWs1iANqRjJ8=; b=qOhF2Rv0iq0sdkYdbTDo6zWzvXOlll/+3bH6I+YYgoCSVtNPmwY7RZ1Ou7jdqdjnku AmLRPNOsyYkJMEXwdqdsFajaRFgcd+i76OkBgoRWOl02VHgxIhXijhH4t1Du8dozoGR2 j3dh5yCoGSLoA8mCH118zzJwSjec7vlGh3FJ6Y9CpI1Prh2AohzEXPcI8cBEjWroF0b3 nuNkYT65/Bu60MK/CAqgH7KcHMwiz8H8jN3zPaS6xzTuPKaUnS7FcnOIE5qVA6WH62X3 8vzWXiZVipemU2WrvcOBdckhQTGnFwsIl8/DYmp4p3YSxFtVCom6HLlprSKDShEyt2Jw +/Qg== X-Gm-Message-State: AOJu0Yzjyd5WTpEB5ce39aMTkRyFBIfj64+lIpL1/K557tTBMi5weP5p R4X4FnCf30yW5jWSAxcSnIMKpHTc4nc13eXmsGSo2/6WeKhQmxcR5w9xTT22 X-Received: by 2002:a5e:db46:0:b0:7f5:bd0c:aada with SMTP id ca18e2360f4ac-80003f8a1c3mr1777697439f.18.1720970189705; Sun, 14 Jul 2024 08:16:29 -0700 (PDT) Received: from [192.168.0.171] ([203.192.244.245]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-70b7ecc9d36sm2687078b3a.205.2024.07.14.08.16.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 14 Jul 2024 08:16:29 -0700 (PDT) Message-ID: <7ff34a9f-1e34-48a9-a3a5-b3dd5da60b98@gmail.com> Date: Sun, 14 Jul 2024 20:46:27 +0530 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: ffmpeg-devel@ffmpeg.org References: <691930bc-b3e6-8185-2a7e-cf90462d4376@gmail.com> <11d4dd69-f7f0-458a-a4da-fb6dc9a2f4f9@gmail.com> Content-Language: en-US From: CoderVenkat In-Reply-To: Subject: [FFmpeg-devel] [PATCH v3] avformat/hls: Fixed incorrect behaviour of default X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Steven Liu Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: kDzi+DAG8xkg Hi, I separated both into different for loops, and changed the order of some checks so they aren't unnecessarily done. Attached patch to this mail. Thanks, vckt From 1ccc029801699c21db2fad8e20ddfab226068c37 Mon Sep 17 00:00:00 2001 From: vckt Date: Fri, 5 Jul 2024 18:51:32 +0530 Subject: [PATCH v3] avformat/hls: Fixed incorrect behaviour of default setting, added autoselect and forced In absence of defualt in var_stream_map, it was setting default=yes on every stream, but according to RFC8216 4.3.4.1 only one stream in a default group may have that. Additionally added support for autoselect=yes/no, whose presence combined with default means that it MUST be YES. Similarly forced=yes/no for subtitle stream. Showed sample output of incorrectness in bug #11088 Signed-off-by: vckt Signed-off-by: vckt --- libavformat/dashenc.c | 3 ++- libavformat/hlsenc.c | 47 +++++++++++++++++++++++++++++++++++---- libavformat/hlsplaylist.c | 26 +++++++++++++++------- libavformat/hlsplaylist.h | 6 +++-- 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d4a6fe0304..898a227cbe 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1273,6 +1273,7 @@ static int write_manifest(AVFormatContext *s, int final) const char *audio_group = "A1"; char audio_codec_str[128] = "\0"; int is_default = 1; + int autoselect = 0; int max_audio_bitrate = 0; for (i = 0; i < s->nb_streams; i++) { @@ -1285,7 +1286,7 @@ static int write_manifest(AVFormatContext *s, int final) continue; get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); ff_hls_write_audio_rendition(c->m3u8_out, audio_group, - playlist_file, NULL, i, is_default, + playlist_file, NULL, i, is_default, autoselect, s->streams[i]->codecpar->ch_layout.nb_channels); max_audio_bitrate = FFMAX(st->codecpar->bit_rate + os->muxer_overhead, max_audio_bitrate); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 274de00f9a..86c1c9a274 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -184,6 +184,8 @@ typedef struct VariantStream { unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ int is_default; /* default status of audio group */ + int autoselect; /* autoselect by system language */ + int forced; /* forced status of subtitle stream */ const char *language; /* audio language name */ const char *agroup; /* audio group name */ const char *sgroup; /* subtitle group name */ @@ -1434,6 +1436,31 @@ static int create_master_playlist(AVFormatContext *s, avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid); } + /* Check only one default is present in a group */ + for (i = 0; i < hls->nb_varstreams; i++) { + vs = &(hls->var_streams[i]); + for (j = 0; j < hls->nb_varstreams; j++) { + if (i != j) { + temp_vs = &(hls->var_streams[j]); + if (vs->agroup && temp_vs->agroup && + !vs->has_video && !temp_vs->has_video) { + if (!av_strcasecmp(vs->agroup, temp_vs->agroup) && + vs->is_default && temp_vs->is_default) { + av_log(s, AV_LOG_ERROR, "Two streams in an agroup can not be default\n"); + goto fail; + } + } else if (vs->sgroup && temp_vs->sgroup && + !vs->has_video && !temp_vs->has_video) { + if (!av_strcasecmp(vs->sgroup, temp_vs->sgroup) && + vs->is_default && temp_vs->is_default) { + av_log(s, AV_LOG_ERROR, "Two streams in an sgroup can not be default\n"); + goto fail; + } + } + } + } + } + /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { vs = &(hls->var_streams[i]); @@ -1452,7 +1479,7 @@ static int create_master_playlist(AVFormatContext *s, if (vs->streams[j]->codecpar->ch_layout.nb_channels > nb_channels) nb_channels = vs->streams[j]->codecpar->ch_layout.nb_channels; - ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1, nb_channels); + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 0, vs->autoselect, nb_channels); } /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ @@ -1533,7 +1560,7 @@ static int create_master_playlist(AVFormatContext *s, break; } - ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1); + ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 0, vs->autoselect, vs->forced); } if (!hls->has_default_key || !hls->has_video_m3u8) { @@ -2032,6 +2059,8 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) int nb_varstreams = 0, nb_streams; char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval; const char *val; + const size_t strlen_yes = strlen("YES"); + const size_t strlen_1 = strlen("1"); /* used in multiple arguments */ /** * Expected format for var_stream_map string is as below: @@ -2100,10 +2129,20 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) vs->language = val; continue; } else if (av_strstart(keyval, "default:", &val)) { - vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) || - (!av_strncasecmp(val, "1", strlen("1")))); + vs->is_default = (!av_strncasecmp(val, "YES", strlen_yes) || + (!av_strncasecmp(val, "1", strlen_1))); hls->has_default_key = 1; continue; + } else if (av_strstart(keyval, "autoselect:", &val)) { + vs->autoselect = (!av_strncasecmp(val, "YES", strlen_yes) || + (!av_strncasecmp(val, "1", strlen_1))) || + (hls->has_default_key && vs->is_default); + /* autoselect must = 1 if default = 1 */ + continue; + } else if (av_strstart(keyval, "forced:", &val)) { + vs->forced = (!av_strncasecmp(val, "YES", strlen_yes) || + (!av_strncasecmp(val, "1", strlen_1))); + continue; } else if (av_strstart(keyval, "name:", &val)) { vs->varname = val; continue; diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index f8a6977702..094bb56689 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -39,16 +39,20 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, - int name_id, int is_default, int nb_channels) + int name_id, int is_default, + int autoselect, int nb_channels) { if (!out || !agroup || !filename) return; avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", agroup); - avio_printf(out, ",NAME=\"audio_%d\",DEFAULT=%s,", name_id, is_default ? "YES" : "NO"); - if (language) { + avio_printf(out, ",NAME=\"audio_%d\",", name_id); + if (is_default) + avio_printf(out, "DEFAULT=YES,"); + if (autoselect) + avio_printf(out, "AUTOSELECT=YES,"); + if (language) avio_printf(out, "LANGUAGE=\"%s\",", language); - } if (nb_channels) { avio_printf(out, "CHANNELS=\"%d\",", nb_channels); } @@ -57,16 +61,22 @@ void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, - int name_id, int is_default) + int name_id, int is_default, + int autoselect, int forced) { if (!out || !filename) return; avio_printf(out, "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"%s\"", sgroup); - avio_printf(out, ",NAME=\"subtitle_%d\",DEFAULT=%s,", name_id, is_default ? "YES" : "NO"); - if (language) { + avio_printf(out, ",NAME=\"subtitle_%d\",", name_id); + if (is_default) + avio_printf(out, "DEFAULT=YES,"); + if (autoselect) + avio_printf(out, "AUTOSELECT=YES,"); + if (forced) + avio_printf(out, "FORCED=YES,"); + if (language) avio_printf(out, "LANGUAGE=\"%s\",", language); - } avio_printf(out, "URI=\"%s\"\n", filename); } diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index d7aa44d8dc..41e640a09a 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -38,10 +38,12 @@ typedef enum { void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, - int name_id, int is_default, int nb_channels); + int name_id, int is_default, + int autoselect, int nb_channels); void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, - int name_id, int is_default); + int name_id, int is_default, + int autoselect, int forced); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, int avg_bandwidth, const char *filename, const char *agroup,