[FFmpeg-devel] [PATCH 8/8] avformat: Immersive Audio Model and Formats muxer
Signed-off-by: James Almer --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/iamf_writer.c | 860 ++ libavformat/iamf_writer.h | 51 +++ libavformat/iamfenc.c | 387 + 5 files changed, 1300 insertions(+) create mode 100644 libavformat/iamf_writer.c create mode 100644 libavformat/iamf_writer.h create mode 100644 libavformat/iamfenc.c diff --git a/libavformat/Makefile b/libavformat/Makefile index f23c22792b..581e378d95 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -259,6 +259,7 @@ OBJS-$(CONFIG_HLS_DEMUXER) += hls.o hls_sample_encryption.o OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o OBJS-$(CONFIG_IAMF_DEMUXER) += iamfdec.o iamf_parse.o iamf.o +OBJS-$(CONFIG_IAMF_MUXER)+= iamfenc.o iamf_writer.o iamf.o OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o OBJS-$(CONFIG_ICO_MUXER) += icoenc.o OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 6e520b78a6..ce6be5f04d 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -213,6 +213,7 @@ extern const AVInputFormat ff_hls_demuxer; extern const FFOutputFormat ff_hls_muxer; extern const AVInputFormat ff_hnm_demuxer; extern const AVInputFormat ff_iamf_demuxer; +extern const FFOutputFormat ff_iamf_muxer; extern const AVInputFormat ff_ico_demuxer; extern const FFOutputFormat ff_ico_muxer; extern const AVInputFormat ff_idcin_demuxer; diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c new file mode 100644 index 00..9962845049 --- /dev/null +++ b/libavformat/iamf_writer.c @@ -0,0 +1,860 @@ +/* + * Immersive Audio Model and Formats muxing helpers and structs + * Copyright (c) 2023 James Almer + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/iamf.h" +#include "libavutil/mem.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/flac.h" +#include "libavcodec/mpeg4audio.h" +#include "libavcodec/put_bits.h" +#include "avformat.h" +#include "avio_internal.h" +#include "iamf.h" +#include "iamf_writer.h" + + +static int update_extradata(IAMFCodecConfig *codec_config) +{ +GetBitContext gb; +PutBitContext pb; +int ret; + +switch(codec_config->codec_id) { +case AV_CODEC_ID_OPUS: +if (codec_config->extradata_size < 19) +return AVERROR_INVALIDDATA; +codec_config->extradata_size -= 8; +memmove(codec_config->extradata, codec_config->extradata + 8, codec_config->extradata_size); +AV_WB8(codec_config->extradata + 1, 2); // set channels to stereo +break; +case AV_CODEC_ID_FLAC: { +uint8_t buf[13]; + +init_put_bits(&pb, buf, sizeof(buf)); +ret = init_get_bits8(&gb, codec_config->extradata, codec_config->extradata_size); +if (ret < 0) +return ret; + +put_bits32(&pb, get_bits_long(&gb, 32)); // min/max blocksize +put_bits64(&pb, 48, get_bits64(&gb, 48)); // min/max framesize +put_bits(&pb, 20, get_bits(&gb, 20)); // samplerate +skip_bits(&gb, 3); +put_bits(&pb, 3, 1); // set channels to stereo +ret = put_bits_left(&pb); +put_bits(&pb, ret, get_bits(&gb, ret)); +flush_put_bits(&pb); + +memcpy(codec_config->extradata, buf, sizeof(buf)); +break; +} +default: +break; +} + +return 0; +} + +static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg, + IAMFCodecConfig *codec_config) +{ +const AVStream *st = stg->streams[0]; +IAMFCodecConfig **tmp; +int j, ret = 0; + +codec_config->codec_id = st->codecpar->codec_id; +codec_config->sample_rate = st->codecpar->sample_rate; +codec_config->codec_tag = st->codecpar->codec_tag; +codec_config->nb_samples = st->codecpar->frame_size; +codec_config->seek_preroll = st->codecpar->seek_preroll; +if (st->codecpar->extradata_size) { +codec_config->extradata = av
[FFmpeg-devel] [PATCH 8/8] avformat: Immersive Audio Model and Formats muxer
Signed-off-by: James Almer --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/iamf_writer.c | 823 ++ libavformat/iamf_writer.h | 51 +++ libavformat/iamfenc.c | 388 ++ 5 files changed, 1264 insertions(+) create mode 100644 libavformat/iamf_writer.c create mode 100644 libavformat/iamf_writer.h create mode 100644 libavformat/iamfenc.c diff --git a/libavformat/Makefile b/libavformat/Makefile index f23c22792b..581e378d95 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -259,6 +259,7 @@ OBJS-$(CONFIG_HLS_DEMUXER) += hls.o hls_sample_encryption.o OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o OBJS-$(CONFIG_IAMF_DEMUXER) += iamfdec.o iamf_parse.o iamf.o +OBJS-$(CONFIG_IAMF_MUXER)+= iamfenc.o iamf_writer.o iamf.o OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o OBJS-$(CONFIG_ICO_MUXER) += icoenc.o OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 6e520b78a6..ce6be5f04d 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -213,6 +213,7 @@ extern const AVInputFormat ff_hls_demuxer; extern const FFOutputFormat ff_hls_muxer; extern const AVInputFormat ff_hnm_demuxer; extern const AVInputFormat ff_iamf_demuxer; +extern const FFOutputFormat ff_iamf_muxer; extern const AVInputFormat ff_ico_demuxer; extern const FFOutputFormat ff_ico_muxer; extern const AVInputFormat ff_idcin_demuxer; diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c new file mode 100644 index 00..fc31174b53 --- /dev/null +++ b/libavformat/iamf_writer.c @@ -0,0 +1,823 @@ +/* + * Immersive Audio Model and Formats muxing helpers and structs + * Copyright (c) 2023 James Almer + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/iamf.h" +#include "libavutil/mem.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/flac.h" +#include "libavcodec/mpeg4audio.h" +#include "libavcodec/put_bits.h" +#include "avformat.h" +#include "avio_internal.h" +#include "iamf.h" +#include "iamf_writer.h" + + +static int update_extradata(IAMFCodecConfig *codec_config) +{ +GetBitContext gb; +PutBitContext pb; +int ret; + +switch(codec_config->codec_id) { +case AV_CODEC_ID_OPUS: +if (codec_config->extradata_size < 19) +return AVERROR_INVALIDDATA; +codec_config->extradata_size -= 8; +memmove(codec_config->extradata, codec_config->extradata + 8, codec_config->extradata_size); +AV_WB8(codec_config->extradata + 1, 2); // set channels to stereo +break; +case AV_CODEC_ID_FLAC: { +uint8_t buf[13]; + +init_put_bits(&pb, buf, sizeof(buf)); +ret = init_get_bits8(&gb, codec_config->extradata, codec_config->extradata_size); +if (ret < 0) +return ret; + +put_bits32(&pb, get_bits_long(&gb, 32)); // min/max blocksize +put_bits64(&pb, 48, get_bits64(&gb, 48)); // min/max framesize +put_bits(&pb, 20, get_bits(&gb, 20)); // samplerate +skip_bits(&gb, 3); +put_bits(&pb, 3, 1); // set channels to stereo +ret = put_bits_left(&pb); +put_bits(&pb, ret, get_bits(&gb, ret)); +flush_put_bits(&pb); + +memcpy(codec_config->extradata, buf, sizeof(buf)); +break; +} +default: +break; +} + +return 0; +} + +static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg, + IAMFCodecConfig *codec_config) +{ +const AVStream *st = stg->streams[0]; +IAMFCodecConfig **tmp; +int j, ret = 0; + +codec_config->codec_id = st->codecpar->codec_id; +codec_config->sample_rate = st->codecpar->sample_rate; +codec_config->codec_tag = st->codecpar->codec_tag; +codec_config->nb_samples = st->codecpar->frame_size; +codec_config->seek_preroll = st->codecpar->seek_preroll; +if (st->codecpar->extradata_size) { +codec_config->extradata = a