From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id A261A47E8D for ; Mon, 30 Oct 2023 01:07:42 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A39A268CCA9; Mon, 30 Oct 2023 03:07:39 +0200 (EET) Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 76E2868CC30 for ; Mon, 30 Oct 2023 03:07:33 +0200 (EET) Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-1efba24b038so445685fac.1 for ; Sun, 29 Oct 2023 18:07:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698628051; x=1699232851; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NkMI0AjojFPwQVJOcAOABkie8VkqsN0/TgnbthC9RFg=; b=HNIfiR8QjpFN4AaZed2daQU1oadychnGhXxPpd/bQ86Qk7k1CINndj+fM8/o4Q/EzT LFIvqychU7S7OazntmQioK6TgNBhwbzKlz77lbynr4/l3e2K6ym4Sm8K4tK8jSCIJ7Y7 bZqBuh5SDi7qh/t9/ITIxV85J5TKOqO/0qKRvhuGCZxCP6+HVH22m/gZ1wDmwgShRztB /PeAzPh5Ju+zPH/KLBsC1QbQ0A3veWotUsihn779Sg/Z8ReVZ1K/eIcDb68s+FGb4y/g pLfpSUkmuquPxFCl0WVZPGEtYt/WDQG+L16ZJ7b5ro/4Y4NZzsybQ1j3qq1qhuaIz4HJ nYjA== X-Gm-Message-State: AOJu0Yy67XEEbt9XuoqqZlWUUmi4nHI7aay92djy8AO79eugPW8EKSAL tS4ZTdVSZ17Wn1i4TLIR2ubo8MNgsM0g8Q== X-Google-Smtp-Source: AGHT+IH4MLbjzYJb4AYLUWYx1unaLLr1LtT7lUxyE1t1ChkPlLFUELyUMGnWuXySwJyoveEGin6jLA== X-Received: by 2002:a05:6871:210e:b0:1ea:7463:1b8f with SMTP id sa14-20020a056871210e00b001ea74631b8fmr9243276oab.0.1698628051392; Sun, 29 Oct 2023 18:07:31 -0700 (PDT) Received: from romains-mbp.lan (ip24-252-77-224.no.no.cox.net. [24.252.77.224]) by smtp.gmail.com with ESMTPSA id bt33-20020a05683039e100b006ce2b90d0cesm1260138otb.24.2023.10.29.18.07.30 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 29 Oct 2023 18:07:30 -0700 (PDT) From: Romain Beauxis To: ffmpeg-devel@ffmpeg.org Date: Sun, 29 Oct 2023 20:05:50 -0500 Message-Id: <20231030010549.59349-1-toots@rastageeks.org> X-Mailer: git-send-email 2.39.3 (Apple Git-145) MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] Extract av_hls_codec_attr 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: Romain Beauxis Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: The logic for extracting HLS codec attribute strings is very useful and can be re-used in many different situations when working with HLS streams using libavcodec/libavformat. This patch extracts the function's code and places it into a publicly available function. --- libavcodec/Makefile | 2 + libavcodec/hls.c | 105 +++++++++++++++++++++++++++++++++++++++++++ libavcodec/hls.h | 42 +++++++++++++++++ libavformat/hlsenc.c | 83 +++------------------------------- 4 files changed, 155 insertions(+), 77 deletions(-) create mode 100644 libavcodec/hls.c create mode 100644 libavcodec/hls.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 580a8d6b54..b3b2b18980 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -16,6 +16,7 @@ HEADERS = ac3_parser.h \ dirac.h \ dv_profile.h \ dxva2.h \ + hls.h \ jni.h \ mediacodec.h \ packet.h \ @@ -47,6 +48,7 @@ OBJS = ac3_parser.o \ get_buffer.o \ imgconvert.o \ jni.o \ + hls.o \ mathtables.o \ mediacodec.o \ mpeg12framerate.o \ diff --git a/libavcodec/hls.c b/libavcodec/hls.c new file mode 100644 index 0000000000..59ab0c4819 --- /dev/null +++ b/libavcodec/hls.c @@ -0,0 +1,105 @@ +/* + * HLS public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hls.h" +#include "libavutil/intreadwrite.h" +#include "libavformat/avc.h" + +int av_hls_codec_attr(AVStream *st, char *attr, size_t attr_len) { + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { + uint8_t *data = st->codecpar->extradata; + if (data) { + const uint8_t *p; + + if (AV_RB32(data) == 0x01 && (data[4] & 0x1F) == 7) + p = &data[5]; + else if (AV_RB24(data) == 0x01 && (data[3] & 0x1F) == 7) + p = &data[4]; + else if (data[0] == 0x01) /* avcC */ + p = &data[1]; + else + return AVERROR_INVALIDDATA; + snprintf(attr, attr_len, + "avc1.%02x%02x%02x", p[0], p[1], p[2]); + } else { + return AVERROR_INVALIDDATA; + } + } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) { + uint8_t *data = st->codecpar->extradata; + int profile = AV_PROFILE_UNKNOWN; + int level = AV_LEVEL_UNKNOWN; + + if (st->codecpar->profile != AV_PROFILE_UNKNOWN) + profile = st->codecpar->profile; + if (st->codecpar->level != AV_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 + 19) < 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] & 0x7E) == 0x42)) { + uint8_t *rbsp_buf; + 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); + rbsp_buf = ff_nal_unit_extract_rbsp(data, remain_size, &rbsp_size, 0); + if (!rbsp_buf) + return AVERROR_INVALIDDATA; + 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 != AV_PROFILE_UNKNOWN && + level != AV_LEVEL_UNKNOWN) { + snprintf(attr, attr_len, "%s.%d.4.L%d.B01", av_fourcc2str(st->codecpar->codec_tag), profile, level); + } else + return AVERROR_INVALIDDATA; + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { + snprintf(attr, attr_len, "mp4a.40.33"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) { + snprintf(attr, attr_len, "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, attr_len, "mp4a.40.2"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { + snprintf(attr, attr_len, "ac-3"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) { + snprintf(attr, attr_len, "ec-3"); + } else { + return AVERROR_INVALIDDATA; + } + + return 0; +} diff --git a/libavcodec/hls.h b/libavcodec/hls.h new file mode 100644 index 0000000000..c9696386b7 --- /dev/null +++ b/libavcodec/hls.h @@ -0,0 +1,42 @@ +/* + * HLS public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * A public API for HLS codec information + */ + +#ifndef AVCODEC_HLS_H +#define AVCODEC_HLS_H + +#include "libavformat/avformat.h" + +/** + * Write a NULL-terminated string representing the codec attributes + * associated with the given AVStream. + * + * @param st stream to extract codec attributes from + * @param attr buffer to write to wanted payload size + * @param attr_len size of the buffer + * @return 0 on success, a negative AVERROR code on failure + */ +int av_hls_codec_attr(AVStream *st, char *attr, size_t attr_len); + +#endif diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 4ef84c05c1..1c0a35c36d 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -40,6 +40,7 @@ #include "libavutil/time_internal.h" #include "libavcodec/defs.h" +#include "libavcodec/hls.h" #include "avformat.h" #include "avio_internal.h" @@ -344,89 +345,17 @@ static void write_codec_attr(AVStream *st, VariantStream *vs) { int codec_strlen = strlen(vs->codec_attr); char attr[32]; + int ret; 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) { - const uint8_t *p; - - if (AV_RB32(data) == 0x01 && (data[4] & 0x1F) == 7) - p = &data[5]; - else if (AV_RB24(data) == 0x01 && (data[3] & 0x1F) == 7) - p = &data[4]; - else if (data[0] == 0x01) /* avcC */ - p = &data[1]; - else - goto fail; - snprintf(attr, sizeof(attr), - "avc1.%02x%02x%02x", p[0], p[1], p[2]); - } else { - goto fail; - } - } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) { - uint8_t *data = st->codecpar->extradata; - int profile = AV_PROFILE_UNKNOWN; - int level = AV_LEVEL_UNKNOWN; - - if (st->codecpar->profile != AV_PROFILE_UNKNOWN) - profile = st->codecpar->profile; - if (st->codecpar->level != AV_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 + 19) < 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] & 0x7E) == 0x42)) { - uint8_t *rbsp_buf; - 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); - 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 != AV_PROFILE_UNKNOWN && - level != AV_LEVEL_UNKNOWN) { - snprintf(attr, sizeof(attr), "%s.%d.4.L%d.B01", av_fourcc2str(st->codecpar->codec_tag), profile, level); - } 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; - } + ret = av_hls_codec_attr(st, attr, sizeof(attr)); + if (ret < 0) + goto fail; + // Don't write the same attribute multiple times if (!av_stristr(vs->codec_attr, attr)) { snprintf(vs->codec_attr + codec_strlen, -- 2.39.3 (Apple Git-145) _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".