From ac883016d94bb95354e2824a501702f64c9ad945 Mon Sep 17 00:00:00 2001 From: liushuai Date: Fri, 1 Nov 2024 10:54:16 +0800 Subject: [PATCH] =?UTF-8?q?av3a=E6=A0=BC=E5=BC=8F=E5=B0=81=E8=A3=85?= =?UTF-8?q?=E5=92=8C=E8=A7=A3=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liushuai --- BUILD.gn | 1 + config_components.h | 2 + libavcodec/av3a.h | 270 +++++++++++++++++++ libavcodec/av3a_parser.c | 555 ++++++++++----------------------------- libavcodec/codec_desc.c | 4 +- libavcodec/utils.c | 2 +- libavformat/Makefile | 2 + libavformat/allformats.c | 2 + libavformat/av3adec.c | 418 +++++++++++++++++++++++++++++ libavformat/isom_tags.c | 2 +- libavformat/mov.c | 119 +++++++++ libavformat/movenc.c | 78 +++++- libavformat/mpegts.c | 3 +- libavformat/mpegts.h | 1 + libavformat/mpegtsenc.c | 4 + libavformat/rawenc.c | 14 + ohos_config.sh | 8 +- 17 files changed, 1054 insertions(+), 431 deletions(-) create mode 100644 libavcodec/av3a.h create mode 100644 libavformat/av3adec.c diff --git a/BUILD.gn b/BUILD.gn index 96cd219b89..18598ceb15 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1118,6 +1118,7 @@ ohos_source_set("ffmpeg_dynamic") { # "//third_party/ffmpeg/libavformat/au.c", "//third_party/ffmpeg/libavformat/av1.c", "//third_party/ffmpeg/libavformat/avc.c", + "//third_party/ffmpeg/libavformat/av3adec.c", # "//third_party/ffmpeg/libavformat/avidec.c", "//third_party/ffmpeg/libavformat/avio.c", diff --git a/config_components.h b/config_components.h index 7c58b09e76..377f11d270 100644 --- a/config_components.h +++ b/config_components.h @@ -1563,6 +1563,7 @@ #define CONFIG_AST_DEMUXER 1 #define CONFIG_AU_DEMUXER 1 #define CONFIG_AV1_DEMUXER 1 +#define CONFIG_AV3A_DEMUXER 1 #define CONFIG_AVI_DEMUXER 1 #define CONFIG_AVISYNTH_DEMUXER 0 #define CONFIG_AVR_DEMUXER 1 @@ -1887,6 +1888,7 @@ #define CONFIG_AST_MUXER 1 #define CONFIG_ASF_STREAM_MUXER 1 #define CONFIG_AU_MUXER 1 +#define CONFIG_AV3A_MUXER 1 #define CONFIG_AVI_MUXER 1 #define CONFIG_AVIF_MUXER 1 #define CONFIG_AVM2_MUXER 1 diff --git a/libavcodec/av3a.h b/libavcodec/av3a.h new file mode 100644 index 0000000000..d7ac97fa31 --- /dev/null +++ b/libavcodec/av3a.h @@ -0,0 +1,270 @@ +/* + * AV3A Format Common Header + * + * 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 + */ + +#ifndef AVCODEC_AV3A_H +#define AVCODEC_AV3A_H + +#include "libavutil/samplefmt.h" + +/* AATF header */ +#define AV3A_MAX_NBYTES_HEADER 9 +#define AV3A_AUDIO_SYNC_WORD 0xFFF +#define AV3A_AUDIO_FRAME_SIZE 1024 +#define AV3A_CHANNEL_LAYOUT_SIZE 15 +#define AV3A_SIZE_BITRATE_TABLE 16 +#define AV3A_SIZE_FS_TABLE 9 +#define AV3A_SIZE_RESOLUTION_TABLE 3 + +/* Channel Layout */ +#define AV3A_CH_LAYOUT_MONO (AV_CH_LAYOUT_MONO) +#define AV3A_CH_LAYOUT_STEREO (AV_CH_LAYOUT_STEREO) +#define AV3A_CH_LAYOUT_4POINT0 (AV3A_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER) +#define AV3A_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT1) +#define AV3A_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT) +#define AV3A_CH_LAYOUT_5POINT1POINT2 (AV_CH_LAYOUT_5POINT1|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT) +#define AV3A_CH_LAYOUT_7POINT1POINT2 (AV3A_CH_LAYOUT_7POINT1|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT) +#define AV3A_CH_LAYOUT_5POINT1POINT4 (AV_CH_LAYOUT_5POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV3A_CH_LAYOUT_7POINT1POINT4 (AV3A_CH_LAYOUT_7POINT1|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT) +#define AV3A_CH_AUDIO_OBJECT (AV_CHAN_UNKNOWN) + +typedef enum { + CHANNEL_CONFIG_MONO = 0, /* Mono = 0 */ + CHANNEL_CONFIG_STEREO = 1, /* Stereo = 1 */ + CHANNEL_CONFIG_MC_5_1 = 2, /* 5.1 = 2 */ + CHANNEL_CONFIG_MC_7_1 = 3, /* 7.1 = 3 */ + CHANNEL_CONFIG_MC_10_2 = 4, /* 10.2 = 4 */ + CHANNEL_CONFIG_MC_22_2 = 5, /* 22.2 = 5 */ + CHANNEL_CONFIG_MC_4_0 = 6, /* 4.0 = 6 */ + CHANNEL_CONFIG_MC_5_1_2 = 7, /* 5.1.2 = 7 */ + CHANNEL_CONFIG_MC_5_1_4 = 8, /* 5.1.4 = 8 */ + CHANNEL_CONFIG_MC_7_1_2 = 9, /* 7.1.2 = 9 */ + CHANNEL_CONFIG_MC_7_1_4 = 10, /* 7.1.4 = 10 */ + CHANNEL_CONFIG_HOA_ORDER1 = 11, /* FOA = 11 */ + CHANNEL_CONFIG_HOA_ORDER2 = 12, /* HOA2 = 12 */ + CHANNEL_CONFIG_HOA_ORDER3 = 13, /* HOA3 = 13 */ + CHANNEL_CONFIG_UNKNOWN = 14 /* UNKNOWN = 14 */ +} AV3AChannelConfig; + +typedef struct { + int16_t sync_word; /* sync word */ + int16_t audio_codec_id; /* audio codec id */ + int16_t anc_data; /* anc data */ + int16_t nn_type; /* neural network type */ + int16_t coding_profile; /* coding profile */ + int16_t sampling_frequency_index; /* samping rate index */ + int16_t channel_number_index; /* channel number index */ + int16_t bitrate_index; /* bitrate index */ + int16_t soundBedType; /* soundbed type */ + int16_t object_channel_number; /* object channel number */ + int16_t bitrate_index_per_channel; /* bitrate per object */ + int16_t order; /* ambisonics order */ + int16_t resolution_index; /* resolution index */ + + int32_t sampling_rate; /* sampling rate */ + int64_t total_bitrate; /* total bitrate */ + int16_t sample_format ; /* sample format */ + int16_t resolution; /* resolution */ + int16_t content_type; /* internal content type */ + int16_t nb_channels; /* number of channels (channel configuration) */ + int16_t nb_objects; /* number of objects (object_channel_number + 1) */ + int16_t total_channels; /* total channels */ + int16_t hoa_order; /* ambisonics order (order + 1) */ + int32_t ch_layout_mask; /* channel layout mask */ +} AATFHeaderInfo; + +// bitrate table for mono +static const int64_t ff_av3a_mono_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 16000, 32000, 44000, 56000, 64000, 72000, 80000, 96000, 128000, 144000, + 164000, 192000, 0, 0, 0, 0}; + +// bitrate table for stereo +static const int64_t ff_av3a_stereo_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 24000, 32000, 48000, 64000, 80000, 96000, 128000, 144000, 192000, 256000, + 320000, 0, 0, 0, 0, 0}; + +// bitrate table for MC 5.1 +static const int64_t ff_av3a_mc5p1_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 192000, 256000, 320000, 384000, 448000, 512000, 640000, 720000, 144000, 96000, + 128000, 160000, 0, 0, 0, 0}; + +// bitrate table for MC 7.1 +static const int64_t ff_av3a_mc7p1_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 192000, 480000, 256000, 384000, 576000, 640000, 128000, 160000, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for MC 4.0 +static const int64_t ff_av3a_mc4p0_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 48000, 96000, 128000, 192000, 256000, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for MC 5.1.2 +static const int64_t ff_av3a_mc5p1p2_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 152000, 320000, 480000, 576000, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for MC 5.1.4 +static const int64_t ff_av3a_mc5p1p4_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 176000, 384000, 576000, 704000, 256000, 448000, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for MC 7.1.2 +static const int64_t ff_av3a_mc7p1p2_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 216000, 480000, 576000, 384000, 768000, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for MC 7.1.4 +static const int64_t ff_av3a_mc7p1p4_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 240000, 608000, 384000, 512000, 832000, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +static const int64_t ff_av3a_foa_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 48000, 96000, 128000, 192000, 256000, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +static const int64_t ff_av3a_hoa2_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 192000, 256000, 320000, 384000, 480000, 512000, 640000, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +// bitrate table for HOA order 3 +static const int64_t ff_av3a_hoa3_bitrate_table[AV3A_SIZE_BITRATE_TABLE] = { + 256000, 320000, 384000, 512000, 640000, 896000, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +static const int32_t ff_av3a_sampling_rate_table[AV3A_SIZE_FS_TABLE] = { + 192000, 96000, 48000, 44100, 32000, 24000, 22050, 16000, 8000 +}; + +typedef struct { + int16_t resolution; + enum AVSampleFormat sample_format; +} Av3aSampleFormatMap; + +static const Av3aSampleFormatMap ff_av3a_sample_format_map_table[AV3A_SIZE_RESOLUTION_TABLE] = { + {8, AV_SAMPLE_FMT_U8 }, /* 0: 8 bits */ + {16, AV_SAMPLE_FMT_S16}, /* 1: 16 bits */ + {24, AV_SAMPLE_FMT_S32}, /* 2: 24 bits */ +}; + +typedef struct { + AV3AChannelConfig channel_number_index; + int16_t channels; + const enum AVChannel* channel_layout; + uint64_t mask; +} Av3aChannelConfigMap; + +static const enum AVChannel ff_av3a_default_channel_layout_mono[1] ={ + AV_CHAN_FRONT_CENTER +}; + +static const enum AVChannel ff_av3a_default_channel_layout_stereo[2] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT +}; + +static const enum AVChannel ff_av3a_channel_layout_mc_4_0[4] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, AV_CHAN_BACK_CENTER +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_5_1[6] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_5_1_2[8] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_SIDE_LEFT, AV_CHAN_TOP_SIDE_RIGHT +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_7_1[8] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, + AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_5_1_4[10] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_FRONT_LEFT, AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, AV_CHAN_TOP_BACK_RIGHT +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_7_1_2[10] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, + AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, + AV_CHAN_TOP_SIDE_LEFT, AV_CHAN_TOP_SIDE_RIGHT +}; + +static const enum AVChannel ff_av3a_default_channel_layout_mc_7_1_4[12] ={ + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, + AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, + AV_CHAN_TOP_FRONT_LEFT, AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, AV_CHAN_TOP_BACK_RIGHT +}; + +static const Av3aChannelConfigMap ff_av3a_channels_map_table[AV3A_CHANNEL_LAYOUT_SIZE] = { + { CHANNEL_CONFIG_MONO, 1, ff_av3a_default_channel_layout_mono , AV3A_CH_LAYOUT_MONO, }, + { CHANNEL_CONFIG_STEREO, 2, ff_av3a_default_channel_layout_stereo, AV3A_CH_LAYOUT_STEREO }, + { CHANNEL_CONFIG_MC_5_1, 6, ff_av3a_default_channel_layout_mc_5_1, AV3A_CH_LAYOUT_5POINT1 }, + { CHANNEL_CONFIG_MC_7_1, 8, ff_av3a_default_channel_layout_mc_7_1, AV3A_CH_LAYOUT_7POINT1 }, + { CHANNEL_CONFIG_MC_10_2, 12, NULL, 0L }, /* reserved */ + { CHANNEL_CONFIG_MC_22_2, 24, NULL, 0L }, /* reserved */ + { CHANNEL_CONFIG_MC_4_0, 4, ff_av3a_channel_layout_mc_4_0, AV3A_CH_LAYOUT_4POINT0 }, + { CHANNEL_CONFIG_MC_5_1_2, 8, ff_av3a_default_channel_layout_mc_5_1_2, AV3A_CH_LAYOUT_5POINT1POINT2 }, + { CHANNEL_CONFIG_MC_5_1_4, 10, ff_av3a_default_channel_layout_mc_5_1_4, AV3A_CH_LAYOUT_5POINT1POINT4 }, + { CHANNEL_CONFIG_MC_7_1_2, 10, ff_av3a_default_channel_layout_mc_7_1_2, AV3A_CH_LAYOUT_7POINT1POINT2 }, + { CHANNEL_CONFIG_MC_7_1_4, 12, ff_av3a_default_channel_layout_mc_7_1_4, AV3A_CH_LAYOUT_7POINT1POINT4 }, + { CHANNEL_CONFIG_HOA_ORDER1, 4, NULL, 0L }, + { CHANNEL_CONFIG_HOA_ORDER2, 9, NULL, 0L }, + { CHANNEL_CONFIG_HOA_ORDER3, 16, NULL, 0L }, + { CHANNEL_CONFIG_UNKNOWN, 0, NULL, 0L }, +}; + +typedef struct { + AV3AChannelConfig channel_number_index; + const int64_t *bitrate_table; +} Av3aBitrateMap; + +static const Av3aBitrateMap ff_av3a_bitrate_map_table[15] = { + {CHANNEL_CONFIG_MONO, ff_av3a_mono_bitrate_table }, + {CHANNEL_CONFIG_STEREO, ff_av3a_stereo_bitrate_table }, + {CHANNEL_CONFIG_MC_5_1, ff_av3a_mc5p1_bitrate_table }, + {CHANNEL_CONFIG_MC_7_1, ff_av3a_mc7p1_bitrate_table }, + {CHANNEL_CONFIG_MC_10_2, NULL }, /* reserved */ + {CHANNEL_CONFIG_MC_22_2, NULL }, /* reserved */ + {CHANNEL_CONFIG_MC_4_0, ff_av3a_mc4p0_bitrate_table }, + {CHANNEL_CONFIG_MC_5_1_2, ff_av3a_mc5p1p2_bitrate_table }, + {CHANNEL_CONFIG_MC_5_1_4, ff_av3a_mc5p1p4_bitrate_table }, + {CHANNEL_CONFIG_MC_7_1_2, ff_av3a_mc7p1p2_bitrate_table }, + {CHANNEL_CONFIG_MC_7_1_4, ff_av3a_mc7p1p4_bitrate_table }, + {CHANNEL_CONFIG_HOA_ORDER1, ff_av3a_foa_bitrate_table }, + {CHANNEL_CONFIG_HOA_ORDER2, ff_av3a_hoa2_bitrate_table }, + {CHANNEL_CONFIG_HOA_ORDER3, ff_av3a_hoa3_bitrate_table }, + {CHANNEL_CONFIG_UNKNOWN, NULL }, +}; +#endif /* AVCODEC_AV3A_H */ diff --git a/libavcodec/av3a_parser.c b/libavcodec/av3a_parser.c index 8cbf4bc4af..44fca5d38c 100644 --- a/libavcodec/av3a_parser.c +++ b/libavcodec/av3a_parser.c @@ -1,7 +1,5 @@ /* - * av3a parser - * - * Copyright (c) 2018 James Almer + * AV3A Format Parser * * This file is part of FFmpeg. * @@ -27,478 +25,195 @@ #include "libavutil/intreadwrite.h" #include "parser.h" #include "get_bits.h" +#include "av3a.h" -/* AVS3 header */ -#define AVS3_AUDIO_HEADER_SIZE 7 -#define AVS3_SYNC_WORD_SIZE 2 -#define MAX_NBYTES_FRAME_HEADER 9 -#define AVS3_AUDIO_SYNC_WORD 0xFFF - -#define AVS3_AUDIO_FRAME_SIZE 1024 -#define AVS3_SIZE_BITRATE_TABLE 16 -#define AVS3_SIZE_FS_TABLE 9 - -/* AVS3 Audio Format */ -#define AVS3_MONO_FORMAT 0 -#define AVS3_STEREO_FORMAT 1 -#define AVS3_MC_FORMAT 2 -#define AVS3_HOA_FORMAT 3 -#define AVS3_MIX_FORMAT 4 - -#define AVS3_SIZE_MC_CONFIG_TABLE 10 - -#define AVS3P3_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT) - -typedef struct AVS3AudioParseContext { - int32_t frame_size; - int32_t bitdepth; +typedef struct{ + int16_t audio_codec_id; + int16_t nn_type; + int16_t frame_size; + int16_t resolution; int32_t sample_rate; - uint64_t bit_rate; - uint16_t channels; - uint64_t channel_layout; -} AVS3AParseContext; + int64_t bit_rate; -// AVS3P3 header information -typedef struct { - // header info - uint8_t codec_id; - uint8_t sampling_rate_index; - int32_t sampling_rate; + int16_t content_type; + int16_t channel_number_index; + int16_t nb_channels; + int16_t nb_objects; + int16_t total_channels; +} AV3AParseContext; - uint16_t bitdepth; - uint16_t channels; - uint16_t objects; - uint16_t hoa_order; - uint64_t channel_layout; - int64_t total_bitrate; - // configuration - uint8_t content_type; - uint16_t channel_num_index; - uint16_t total_channels; - uint8_t resolution; - uint8_t nn_type; - uint8_t resolution_index; -} AVS3AHeaderInfo; +static int ff_read_av3a_header_parse(GetBitContext *gb, AATFHeaderInfo* hdf) +{ + int64_t soundbed_bitrate, object_bitrate; -typedef enum { - CHANNEL_CONFIG_MONO = 0, - CHANNEL_CONFIG_STEREO = 1, - CHANNEL_CONFIG_MC_5_1, - CHANNEL_CONFIG_MC_7_1, - CHANNEL_CONFIG_MC_10_2, - CHANNEL_CONFIG_MC_22_2, - CHANNEL_CONFIG_MC_4_0, - CHANNEL_CONFIG_MC_5_1_2, - CHANNEL_CONFIG_MC_5_1_4, - CHANNEL_CONFIG_MC_7_1_2, - CHANNEL_CONFIG_MC_7_1_4, - CHANNEL_CONFIG_HOA_ORDER1, - CHANNEL_CONFIG_HOA_ORDER2, - CHANNEL_CONFIG_HOA_ORDER3, - CHANNEL_CONFIG_UNKNOWN -} AVS3AChannelConfig; + hdf->nb_channels = 0; + hdf->nb_objects = 0; -/* Codec bitrate config struct */ -typedef struct CodecBitrateConfigStructure { - AVS3AChannelConfig channelNumConfig; - const int64_t *bitrateTable; -} CodecBitrateConfig; - -typedef struct McChannelConfigStructure { - const char mcCmdString[10]; - AVS3AChannelConfig channelNumConfig; - const int16_t numChannels; -} McChanelConfig; - -static const McChanelConfig mcChannelConfigTable[AVS3_SIZE_MC_CONFIG_TABLE] = { - {"STEREO", CHANNEL_CONFIG_STEREO, 2}, - {"MC_5_1_0", CHANNEL_CONFIG_MC_5_1, 6}, - {"MC_7_1_0", CHANNEL_CONFIG_MC_7_1, 8}, - {"MC_10_2", CHANNEL_CONFIG_MC_10_2, 12}, - {"MC_22_2", CHANNEL_CONFIG_MC_22_2, 24}, - {"MC_4_0", CHANNEL_CONFIG_MC_4_0, 4}, - {"MC_5_1_2", CHANNEL_CONFIG_MC_5_1_2, 8}, - {"MC_5_1_4", CHANNEL_CONFIG_MC_5_1_4, 10}, - {"MC_7_1_2", CHANNEL_CONFIG_MC_7_1_2, 10}, - {"MC_7_1_4", CHANNEL_CONFIG_MC_7_1_4, 12} -}; - -static const int32_t avs3_samplingrate_table[AVS3_SIZE_FS_TABLE] = { - 192000, 96000, 48000, 44100, 32000, 24000, 22050, 16000, 8000 -}; - -// bitrate table for mono -static const int64_t bitrateTableMono[AVS3_SIZE_BITRATE_TABLE] = { - 16000, 32000, 44000, 56000, 64000, 72000, 80000, 96000, 128000, 144000, 164000, 192000, 0, 0, 0, 0 -}; - -// bitrate table for stereo -static const int64_t bitrateTableStereo[AVS3_SIZE_BITRATE_TABLE] = { - 24000, 32000, 48000, 64000, 80000, 96000, 128000, 144000, 192000, 256000, 320000, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 5.1 -static const int64_t bitrateTableMC5P1[AVS3_SIZE_BITRATE_TABLE] = { - 192000, 256000, 320000, 384000, 448000, 512000, 640000, 720000, 144000, 96000, 128000, 160000, 0, 0, 0, 0 -}; - -// bitrate table for MC 7.1 -static const int64_t bitrateTableMC7P1[AVS3_SIZE_BITRATE_TABLE] = { - 192000, 480000, 256000, 384000, 576000, 640000, 128000, 160000, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 4.0 -static const int64_t bitrateTableMC4P0[AVS3_SIZE_BITRATE_TABLE] = { - 48000, 96000, 128000, 192000, 256000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 5.1.2 -static const int64_t bitrateTableMC5P1P2[AVS3_SIZE_BITRATE_TABLE] = { - 152000, 320000, 480000, 576000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 5.1.4 -static const int64_t bitrateTableMC5P1P4[AVS3_SIZE_BITRATE_TABLE] = { - 176000, 384000, 576000, 704000, 256000, 448000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 7.1.2 -static const int64_t bitrateTableMC7P1P2[AVS3_SIZE_BITRATE_TABLE] = { - 216000, 480000, 576000, 384000, 768000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for MC 7.1.4 -static const int64_t bitrateTableMC7P1P4[AVS3_SIZE_BITRATE_TABLE] = { - 240000, 608000, 384000, 512000, 832000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const int64_t bitrateTableFoa[AVS3_SIZE_BITRATE_TABLE] = { - 48000, 96000, 128000, 192000, 256000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const int64_t bitrateTableHoa2[AVS3_SIZE_BITRATE_TABLE] = { - 192000, 256000, 320000, 384000, 480000, 512000, 640000, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// bitrate table for HOA order 3 -static const int64_t bitrateTableHoa3[AVS3_SIZE_BITRATE_TABLE] = { - 256000, 320000, 384000, 512000, 640000, 896000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// Codec channel number & bitrate config table -// format: {channelConfigIdx, numChannels, bitrateTable} -static const CodecBitrateConfig codecBitrateConfigTable[CHANNEL_CONFIG_UNKNOWN] = { - {CHANNEL_CONFIG_MONO, bitrateTableMono}, - {CHANNEL_CONFIG_STEREO, bitrateTableStereo}, - {CHANNEL_CONFIG_MC_5_1, bitrateTableMC5P1}, - {CHANNEL_CONFIG_MC_7_1, bitrateTableMC7P1}, - {CHANNEL_CONFIG_MC_10_2, NULL}, - {CHANNEL_CONFIG_MC_22_2, NULL}, - {CHANNEL_CONFIG_MC_4_0, bitrateTableMC4P0}, - {CHANNEL_CONFIG_MC_5_1_2, bitrateTableMC5P1P2}, - {CHANNEL_CONFIG_MC_5_1_4, bitrateTableMC5P1P4}, - {CHANNEL_CONFIG_MC_7_1_2, bitrateTableMC7P1P2}, - {CHANNEL_CONFIG_MC_7_1_4, bitrateTableMC7P1P4}, - {CHANNEL_CONFIG_HOA_ORDER1, bitrateTableFoa}, - {CHANNEL_CONFIG_HOA_ORDER2, bitrateTableHoa2}, - {CHANNEL_CONFIG_HOA_ORDER3, bitrateTableHoa3} -}; - -static int read_av3a_frame_header(AVS3AHeaderInfo *hdf, const uint8_t *buf, const int32_t byte_size) -{ - GetBitContext gb; - AVS3AChannelConfig channel_config = CHANNEL_CONFIG_UNKNOWN; - - uint8_t content_type = 0; - uint8_t hoa_order = 0; - uint8_t bitdepth = 0; - uint8_t resolution = 0; - - int16_t channels = 0; - int16_t objects = 0; - uint64_t channel_layout = 0; - - int64_t bitrate_per_obj = 0; - int64_t bitrate_bed_mc = 0; - int64_t total_bitrate = 0; - - uint8_t num_chan_index = 0; - uint8_t obj_brt_idx = 0; - uint8_t bed_brt_idx = 0; - uint8_t brt_idx = 0; - - // Read max header length into bs buffer - init_get_bits8(&gb, buf, MAX_NBYTES_FRAME_HEADER); - - // 12 bits for frame sync word - if (get_bits(&gb, 12) != AVS3_AUDIO_SYNC_WORD) { + hdf->sync_word = get_bits(gb, 12); + if (hdf->sync_word != AV3A_AUDIO_SYNC_WORD) { return AVERROR_INVALIDDATA; } - // 4 bits for codec id - uint8_t codec_id = get_bits(&gb, 4); - if (codec_id != 2) { + hdf->audio_codec_id = get_bits(gb, 4); + if (hdf->audio_codec_id != 2) { return AVERROR_INVALIDDATA; } - // 1 bits for anc data - if (get_bits(&gb, 1) != 0) { + hdf->anc_data = get_bits(gb, 1); + if (hdf->anc_data != 0) { return AVERROR_INVALIDDATA; } - // 3 bits nn type - uint8_t nn_type = get_bits(&gb, 3); + hdf->nn_type = get_bits(gb, 3); + hdf->coding_profile = get_bits(gb, 3); - // 3 bits for coding profile - uint8_t coding_profile = get_bits(&gb, 3); - - // 4 bits for sampling index - uint8_t samping_rate_index = get_bits(&gb, 4); - if (samping_rate_index >= AVS3_SIZE_FS_TABLE) { + hdf->sampling_frequency_index = get_bits(gb, 4); + if (hdf->sampling_frequency_index >= AV3A_SIZE_FS_TABLE) { return AVERROR_INVALIDDATA; } + hdf->sampling_rate = ff_av3a_sampling_rate_table[hdf->sampling_frequency_index]; - // skip 8 bits for CRC first part - skip_bits(&gb, 8); + skip_bits(gb, 8); - if (coding_profile == 0) { - content_type = 0; - - // 7 bits for mono/stereo/MC - num_chan_index = get_bits(&gb, 7); - if (num_chan_index >= CHANNEL_CONFIG_UNKNOWN) { + if (hdf->coding_profile == 0) { + hdf->content_type = 0; /* channel-based */ + hdf->channel_number_index = get_bits(gb, 7); + if ((hdf->channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_22_2)) { return AVERROR_INVALIDDATA; } + hdf->nb_channels = ff_av3a_channels_map_table[hdf->channel_number_index].channels; + } else if (hdf->coding_profile == 1) { + hdf->soundBedType = get_bits(gb, 2); + if (hdf->soundBedType == 0) { + hdf->content_type = 1; /* objects-based */ + hdf->object_channel_number = get_bits(gb, 7); + hdf->nb_objects = hdf->object_channel_number + 1; - channel_config = (AVS3AChannelConfig)num_chan_index; - switch (channel_config) { - case CHANNEL_CONFIG_MONO: - channels = 1; - channel_layout = AV_CH_LAYOUT_MONO; - break; - case CHANNEL_CONFIG_STEREO: - channels = 2; - channel_layout = AV_CH_LAYOUT_STEREO; - break; - case CHANNEL_CONFIG_MC_4_0: - channels = 4; - break; - case CHANNEL_CONFIG_MC_5_1: - channels = 6; - channel_layout = AVS3P3_CH_LAYOUT_5POINT1; - break; - case CHANNEL_CONFIG_MC_7_1: - channels = 8; - channel_layout = AV_CH_LAYOUT_7POINT1; - break; - case CHANNEL_CONFIG_MC_5_1_2: - channels = 8; - break; - case CHANNEL_CONFIG_MC_5_1_4: - channels = 10; - break; - case CHANNEL_CONFIG_MC_7_1_2: - channels = 10; - break; - case CHANNEL_CONFIG_MC_7_1_4: - channels = 12; - break; - case CHANNEL_CONFIG_MC_22_2: - channels = 24; - channel_layout = AV_CH_LAYOUT_22POINT2; - break; - default: - break; - } - } else if (coding_profile == 1) { - // sound bed type, 2bits - uint8_t soundBedType = get_bits(&gb, 2); - - if (soundBedType == 0) { - content_type = 1; - - // for only objects - // object number, 7 bits - objects = get_bits(&gb, 7); - objects += 1; - - // bitrate index for each obj, 4 bits - obj_brt_idx = get_bits(&gb, 4); - - total_bitrate = codecBitrateConfigTable[CHANNEL_CONFIG_MONO].bitrateTable[obj_brt_idx] * objects; - } else if (soundBedType == 1) { - content_type = 2; - - // for MC + objs - // channel number index, 7 bits - num_chan_index = get_bits(&gb, 7); - if (num_chan_index >= CHANNEL_CONFIG_UNKNOWN) { + hdf->bitrate_index_per_channel = get_bits(gb, 4); + if (hdf->bitrate_index_per_channel < 0 ) { + return AVERROR_INVALIDDATA; + } + object_bitrate = ff_av3a_bitrate_map_table[CHANNEL_CONFIG_MONO].bitrate_table[hdf->bitrate_index_per_channel]; + hdf->total_bitrate = object_bitrate * hdf->nb_objects; + } else if (hdf->soundBedType == 1) { + hdf->content_type = 2; /* channel-based + objects */ + hdf->channel_number_index = get_bits(gb, 7); + if ((hdf->channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_22_2)) { return AVERROR_INVALIDDATA; } - // bitrate index for sound bed, 4 bits - bed_brt_idx = get_bits(&gb, 4); - - // object number, 7 bits - objects = get_bits(&gb, 7); - objects += 1; - - // bitrate index for each obj, 4 bits - obj_brt_idx = get_bits(&gb, 4); - - // channelNumIdx for sound bed - channel_config = (AVS3AChannelConfig)num_chan_index; - - // sound bed bitrate - bitrate_bed_mc = codecBitrateConfigTable[channel_config].bitrateTable[bed_brt_idx]; - - // numChannels for sound bed - for (int16_t i = 0; i < AVS3_SIZE_MC_CONFIG_TABLE; i++) { - if (channel_config == mcChannelConfigTable[i].channelNumConfig) { - channels = mcChannelConfigTable[i].numChannels; - } + hdf->bitrate_index = get_bits(gb, 4); + if (hdf->bitrate_index < 0 ) { + return AVERROR_INVALIDDATA; } + hdf->nb_channels = ff_av3a_channels_map_table[hdf->channel_number_index].channels; + soundbed_bitrate = ff_av3a_bitrate_map_table[hdf->channel_number_index].bitrate_table[hdf->bitrate_index]; - // bitrate per obj - bitrate_per_obj = codecBitrateConfigTable[CHANNEL_CONFIG_MONO].bitrateTable[obj_brt_idx]; - - // add num chans and num objs to get total chans - /* channels += objects; */ - - total_bitrate = bitrate_bed_mc + bitrate_per_obj * objects; - } - } else if (coding_profile == 2) { - content_type = 3; - - // 4 bits for HOA order - hoa_order = get_bits(&gb, 4); - hoa_order += 1; - - switch (hoa_order) { - case 1: - channels = 4; - channel_config = CHANNEL_CONFIG_HOA_ORDER1; - break; - case 2: - channels = 9; - channel_config = CHANNEL_CONFIG_HOA_ORDER2; - break; - case 3: - channels = 16; - channel_config = CHANNEL_CONFIG_HOA_ORDER3; - break; - default: - break; - } - } else { - return AVERROR_INVALIDDATA; - } - - // 2 bits for bit depth - uint8_t resolution_index = get_bits(&gb, 2); - switch (resolution_index) { - case 0: - bitdepth = AV_SAMPLE_FMT_U8; - resolution = 8; - break; - case 1: - bitdepth = AV_SAMPLE_FMT_S16; - resolution = 16; - break; - case 2: - resolution = 24; - break; - default: + hdf->object_channel_number = get_bits(gb, 7); + hdf->bitrate_index_per_channel = get_bits(gb, 4); + if (hdf->bitrate_index_per_channel < 0 ) { + return AVERROR_INVALIDDATA; + } + hdf->nb_objects = hdf->object_channel_number + 1; + object_bitrate = ff_av3a_bitrate_map_table[CHANNEL_CONFIG_MONO].bitrate_table[hdf->bitrate_index_per_channel]; + hdf->total_bitrate = soundbed_bitrate + (object_bitrate * hdf->nb_objects); + } else { return AVERROR_INVALIDDATA; - } + } + } else if (hdf->coding_profile == 2) { + hdf->content_type = 3; /* ambisonics */ + hdf->order = get_bits(gb, 4); + hdf->hoa_order += 1; - if (coding_profile != 1) { - // 4 bits for bitrate index - brt_idx = get_bits(&gb, 4); - total_bitrate = codecBitrateConfigTable[channel_config].bitrateTable[brt_idx]; - } - - // 8 bits for CRC second part - skip_bits(&gb, 8); - - /* AVS3P6 M6954-v3 */ - hdf->codec_id = codec_id; - hdf->sampling_rate_index = samping_rate_index; - hdf->sampling_rate = avs3_samplingrate_table[samping_rate_index]; - hdf->bitdepth = bitdepth; - - hdf->nn_type = nn_type; - hdf->content_type = content_type; - - if (hdf->content_type == 0) { - hdf->channel_num_index = num_chan_index; - hdf->channels = channels; - hdf->objects = 0; - hdf->total_channels = channels; - hdf->channel_layout = channel_layout; - } else if (hdf->content_type == 1) { - hdf->objects = objects; - hdf->channels = 0; - hdf->total_channels = objects; - } else if (hdf->content_type == 2) { - hdf->channel_num_index = num_chan_index; - hdf->channels = channels; - hdf->objects = objects; - hdf->total_channels = channels + objects; - hdf->channel_layout = channel_layout; - } else if (hdf->content_type == 3) { - hdf->hoa_order = hoa_order; - hdf->channels = channels; - hdf->total_channels = channels; + if (hdf->hoa_order == 1) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER1; + } else if (hdf->hoa_order == 2) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER2; + } else if (hdf->hoa_order == 3) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER3; + } else { + return AVERROR_INVALIDDATA; + } + hdf->nb_channels = (hdf->hoa_order + 1) * (hdf->hoa_order + 1); } else { return AVERROR_INVALIDDATA; } - hdf->total_bitrate = total_bitrate; - hdf->resolution = resolution; - hdf->resolution_index = resolution_index; + hdf->total_channels = hdf->nb_channels + hdf->nb_objects; + + hdf->resolution_index = get_bits(gb, 2); + if(hdf->resolution_index >= AV3A_SIZE_RESOLUTION_TABLE) { + return AVERROR_INVALIDDATA; + } + hdf->resolution = ff_av3a_sample_format_map_table[hdf->resolution_index].resolution; + hdf->sample_format = ff_av3a_sample_format_map_table[hdf->resolution_index].sample_format; + + if (hdf->coding_profile != 1) { + hdf->bitrate_index = get_bits(gb, 4); + if (hdf->bitrate_index < 0) { + return AVERROR_INVALIDDATA; + } + hdf->total_bitrate = ff_av3a_bitrate_map_table[hdf->channel_number_index].bitrate_table[hdf->bitrate_index]; + } + + skip_bits(gb, 8); return 0; } -static int32_t raw_av3a_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, +static int raw_av3a_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int32_t *poutbuf_size, const uint8_t *buf, int32_t buf_size) { - uint8_t header[MAX_NBYTES_FRAME_HEADER]; - AVS3AHeaderInfo hdf; - hdf.channel_layout = 0; + int ret = 0; + uint8_t header[AV3A_MAX_NBYTES_HEADER]; + AATFHeaderInfo hdf; + GetBitContext gb; + AV3AParseContext *s1 = s->priv_data; - if (buf_size < MAX_NBYTES_FRAME_HEADER) { + if (buf_size < AV3A_MAX_NBYTES_HEADER) { return buf_size; } + memcpy(header, buf, AV3A_MAX_NBYTES_HEADER); - memcpy(header, buf, MAX_NBYTES_FRAME_HEADER); - - // read frame header - int32_t ret = read_av3a_frame_header(&hdf, header, MAX_NBYTES_FRAME_HEADER); - if (ret != 0) { + init_get_bits8(&gb, buf, AV3A_MAX_NBYTES_HEADER); + if ((ret = ff_read_av3a_header_parse(&gb, &hdf)) != 0) { return ret; } - avctx->sample_rate = hdf.sampling_rate; - avctx->bit_rate = hdf.total_bitrate; - avctx->channels = hdf.total_channels; - avctx->channel_layout = hdf.channel_layout; - avctx->frame_size = AVS3_AUDIO_FRAME_SIZE; - s->format = hdf.bitdepth; + s1->audio_codec_id = hdf.audio_codec_id; + s1->nn_type = hdf.nn_type; + s1->frame_size = AV3A_AUDIO_FRAME_SIZE; + s1->resolution = hdf.resolution; + s1->sample_rate = hdf.sampling_rate; + s1->bit_rate = hdf.total_bitrate; + s1->content_type = hdf.content_type; + s1->nb_channels = hdf.nb_channels; + s1->nb_objects = hdf.nb_objects; + s1->total_channels = hdf.total_channels; + s1->channel_number_index = hdf.channel_number_index; + + avctx->codec_id = AV_CODEC_ID_AVS3DA; + avctx->frame_size = AV3A_AUDIO_FRAME_SIZE; + avctx->bits_per_raw_sample = hdf.resolution; + avctx->sample_rate = hdf.sampling_rate; + avctx->bit_rate = hdf.total_bitrate; + + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = hdf.total_channels; - /* return the full packet */ *poutbuf = buf; *poutbuf_size = buf_size; return buf_size; } -#ifdef CONFIG_AV3A_PARSER const AVCodecParser ff_av3a_parser = { .codec_ids = { AV_CODEC_ID_AVS3DA }, - .priv_data_size = sizeof(AVS3AParseContext), + .priv_data_size = sizeof(AV3AParseContext), .parser_parse = raw_av3a_parse, -}; -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index a0219b5a4f..fa50f55bfc 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3242,8 +3242,8 @@ static const AVCodecDescriptor codec_descriptors[] = { { .id = AV_CODEC_ID_AVS3DA, .type = AVMEDIA_TYPE_AUDIO, - .name = "avs_3da", - .long_name = NULL_IF_CONFIG_SMALL("AVS3 Audio"), + .name = "av3a", + .long_name = NULL_IF_CONFIG_SMALL("Audio Vivid"), .props = AV_CODEC_PROP_LOSSY, }, { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 1a8fb83cba..1fe91a072c 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -647,7 +647,7 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, case AV_CODEC_ID_MP2: case AV_CODEC_ID_MUSEPACK7: return 1152; case AV_CODEC_ID_AC3: return 1536; - case AV_CODEC_ID_AVS3DA: return 1024; // avs3p3/audio vivid fixed frame size + case AV_CODEC_ID_AVS3DA: return 1024; } if (sr > 0) { diff --git a/libavformat/Makefile b/libavformat/Makefile index 6c6b779080..645ab945fb 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -131,6 +131,8 @@ OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o OBJS-$(CONFIG_AVI_MUXER) += avienc.o mpegtsenc.o avlanguage.o rawutils.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o +OBJS-$(CONFIG_AV3A_MUXER) += rawenc.o +OBJS-$(CONFIG_AV3A_DEMUXER) += av3adec.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o voc.o OBJS-$(CONFIG_AVS2_DEMUXER) += avs2dec.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 32698b857f..fe5ec4b6fb 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -79,6 +79,8 @@ extern const AVOutputFormat ff_asf_stream_muxer; extern const AVInputFormat ff_au_demuxer; extern const AVOutputFormat ff_au_muxer; extern const AVInputFormat ff_av1_demuxer; +extern const AVOutputFormat ff_av3a_muxer; +extern const AVInputFormat ff_av3a_demuxer; extern const AVInputFormat ff_avi_demuxer; extern const AVOutputFormat ff_avi_muxer; extern const AVOutputFormat ff_avif_muxer; diff --git a/libavformat/av3adec.c b/libavformat/av3adec.c new file mode 100644 index 0000000000..2282954a37 --- /dev/null +++ b/libavformat/av3adec.c @@ -0,0 +1,418 @@ +/* + * Audio Vivid Demuxer + * + * 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 "avformat.h" +#include "avio_internal.h" +#include "internal.h" +#include "rawdec.h" +#include "libavutil/opt.h" +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/channel_layout.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/av3a.h" +#include + +typedef struct { + uint8_t audio_codec_id; + uint8_t sampling_frequency_index; + uint8_t nn_type; + uint8_t content_type; + uint8_t channel_number_index; + uint8_t number_objects; + uint8_t hoa_order; + uint8_t resolution_index; + uint16_t total_bitrate_kbps; +} Av3aFormatContext; + +static int av3a_read_aatf_frame_header(AATFHeaderInfo *hdf, const uint8_t *buf) +{ + int16_t sync_word; + GetBitContext gb; + + hdf->nb_channels = 0; + hdf->nb_objects = 0; + + init_get_bits8(&gb, buf, AV3A_MAX_NBYTES_HEADER); + + sync_word = get_bits(&gb, 12); + if (sync_word != AV3A_AUDIO_SYNC_WORD) { + return AVERROR_INVALIDDATA; + } + + /* codec id */ + hdf->audio_codec_id = get_bits(&gb, 4); + if (hdf->audio_codec_id != 2) { + return AVERROR_INVALIDDATA; + } + + /* anc data */ + hdf->anc_data = get_bits(&gb, 1); + if (hdf->audio_codec_id == 2 && hdf->anc_data) { + return AVERROR_INVALIDDATA; + } + + hdf->nn_type = get_bits(&gb, 3); + if (hdf->audio_codec_id == 2 && (hdf->nn_type != 0 && hdf->nn_type != 1)) { + return AVERROR_INVALIDDATA; + } + + hdf->coding_profile = get_bits(&gb, 3); + + /* sampling rate */ + hdf->sampling_frequency_index = get_bits(&gb, 4); + if (hdf->sampling_frequency_index >= AV3A_SIZE_FS_TABLE) { + return AVERROR_INVALIDDATA; + } + hdf->sampling_rate = ff_av3a_sampling_rate_table[hdf->sampling_frequency_index]; + + skip_bits(&gb, 8); + + if (hdf->coding_profile == 0) { + hdf->content_type = 0; + hdf->channel_number_index = get_bits(&gb, 7); + if ((hdf->channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_22_2)) { + return AVERROR_INVALIDDATA; + } + hdf->nb_channels = ff_av3a_channels_map_table[hdf->channel_number_index].channels; + } else if (hdf->coding_profile == 1) { + hdf->soundBedType = get_bits(&gb, 2); + if (hdf->soundBedType == 0) { + hdf->content_type = 1; + hdf->object_channel_number = get_bits(&gb, 7); + hdf->bitrate_index_per_channel = get_bits(&gb, 4); + if (hdf->bitrate_index_per_channel < 0){ + return AVERROR_INVALIDDATA; + } + hdf->nb_objects = hdf->object_channel_number + 1; + hdf->total_bitrate = ff_av3a_bitrate_map_table[CHANNEL_CONFIG_MONO].bitrate_table[hdf->bitrate_index_per_channel] * hdf->nb_objects; + } else if (hdf->soundBedType == 1) { + hdf->content_type = 2; + hdf->channel_number_index = get_bits(&gb, 7); + if ((hdf->channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (hdf->channel_number_index == CHANNEL_CONFIG_MC_22_2)) { + return AVERROR_INVALIDDATA; + } + hdf->nb_channels = ff_av3a_channels_map_table[hdf->channel_number_index].channels; + hdf->bitrate_index = get_bits(&gb, 4); + if (hdf->bitrate_index < 0) { + return AVERROR_INVALIDDATA; + } + + hdf->object_channel_number = get_bits(&gb, 7); + hdf->nb_objects = hdf->object_channel_number + 1; + hdf->bitrate_index_per_channel = get_bits(&gb, 4); + if (hdf->bitrate_index_per_channel < 0) { + return AVERROR_INVALIDDATA; + } + + hdf->total_bitrate = ff_av3a_bitrate_map_table[hdf->channel_number_index].bitrate_table[hdf->bitrate_index] + + ff_av3a_bitrate_map_table[CHANNEL_CONFIG_MONO].bitrate_table[hdf->bitrate_index_per_channel] * hdf->nb_objects; + } else { + return AVERROR_INVALIDDATA; + } + } else if (hdf->coding_profile == 2) { + /* FOA/HOA */ + hdf->content_type = 3; + hdf->order = get_bits(&gb, 4); + hdf->hoa_order = hdf->order + 1; + hdf->nb_channels = (hdf->hoa_order + 1) * (hdf->hoa_order + 1); + + if (hdf->hoa_order == 1) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER1; + } else if (hdf->hoa_order == 2) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER2; + } else if (hdf->hoa_order == 3) { + hdf->channel_number_index = CHANNEL_CONFIG_HOA_ORDER3; + } else { + return AVERROR_INVALIDDATA; + } + } else { + return AVERROR_INVALIDDATA; + } + + hdf->total_channels = hdf->nb_channels + hdf->nb_objects; + + hdf->resolution_index = get_bits(&gb, 2); + if(hdf->resolution_index >= AV3A_SIZE_RESOLUTION_TABLE) { + return AVERROR_INVALIDDATA; + } + + hdf->resolution = ff_av3a_sample_format_map_table[hdf->resolution_index].resolution; + hdf->sample_format = ff_av3a_sample_format_map_table[hdf->resolution_index].sample_format; + + if (hdf->coding_profile != 1) { + hdf->bitrate_index = get_bits(&gb, 4); + if (hdf->bitrate_index < 0){ + return AVERROR_INVALIDDATA; + } + hdf->total_bitrate = ff_av3a_bitrate_map_table[hdf->channel_number_index].bitrate_table[hdf->bitrate_index]; + } + + skip_bits(&gb, 8); + + return 0; +} + +static int av3a_get_packet_size(AVFormatContext *s) +{ + int read_bytes = 0; + uint16_t sync_word = 0; + uint8_t header[AV3A_MAX_NBYTES_HEADER]; + GetBitContext gb; + int32_t sampling_rate; + int16_t coding_profile, sampling_frequency_index, bitrate_index, channel_number_index, object_bitrate_index; + int16_t objects, hoa_order; + int64_t total_bitrate; + int32_t payload_bytes; + int32_t payloud_bits; + + payload_bytes = 0; + payloud_bits = 0; + + read_bytes = avio_read(s->pb, header, AV3A_MAX_NBYTES_HEADER); + if (read_bytes != AV3A_MAX_NBYTES_HEADER) + return (read_bytes < 0) ? read_bytes : AVERROR_EOF; + + init_get_bits8(&gb, header, AV3A_MAX_NBYTES_HEADER); + + sync_word = get_bits(&gb, 12); + if (sync_word != AV3A_AUDIO_SYNC_WORD) { + return AVERROR_INVALIDDATA; + } + + skip_bits(&gb, 8); + + coding_profile = get_bits(&gb, 3); + sampling_frequency_index = get_bits(&gb, 4); + if (sampling_frequency_index >= AV3A_SIZE_FS_TABLE) { + return AVERROR_INVALIDDATA; + } + sampling_rate = ff_av3a_sampling_rate_table[sampling_frequency_index]; + + skip_bits(&gb, 8); + + if (coding_profile == 0) { + channel_number_index = get_bits(&gb, 7); + if ((channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (channel_number_index == CHANNEL_CONFIG_MC_22_2)) { + return AVERROR_INVALIDDATA; + } + } else if (coding_profile == 1) { + int64_t bitrate_index_per_channel, soundbed_bitrate; + int16_t soundbed_type = get_bits(&gb, 2); + if (soundbed_type == 0) { + objects = get_bits(&gb, 7); + objects += 1; + object_bitrate_index = get_bits(&gb, 4); + if (object_bitrate_index < 0) { + return AVERROR_INVALIDDATA; + } + total_bitrate = ff_av3a_mono_bitrate_table[object_bitrate_index] * objects; + } else if (soundbed_type == 1) { + channel_number_index = get_bits(&gb, 7); + if ((channel_number_index >= CHANNEL_CONFIG_UNKNOWN) || + (channel_number_index == CHANNEL_CONFIG_MC_10_2) || + (channel_number_index == CHANNEL_CONFIG_MC_22_2)) { + return AVERROR_INVALIDDATA; + } + bitrate_index = get_bits(&gb, 4); + objects = get_bits(&gb, 7); + objects += 1; + object_bitrate_index = get_bits(&gb, 4); + if (bitrate_index < 0 || object_bitrate_index < 0){ + return AVERROR_INVALIDDATA; + } + + soundbed_bitrate = ff_av3a_bitrate_map_table[channel_number_index].bitrate_table[bitrate_index]; + bitrate_index_per_channel = ff_av3a_bitrate_map_table[CHANNEL_CONFIG_MONO].bitrate_table[object_bitrate_index]; + total_bitrate = soundbed_bitrate + (bitrate_index_per_channel * objects); + } else { + return AVERROR_INVALIDDATA; + } + } else if (coding_profile == 2) { + hoa_order = get_bits(&gb, 4); + hoa_order += 1; + if(hoa_order == 1) { + channel_number_index = CHANNEL_CONFIG_HOA_ORDER1; + } else if(hoa_order == 2) { + channel_number_index = CHANNEL_CONFIG_HOA_ORDER2; + } else if(hoa_order == 3) { + channel_number_index = CHANNEL_CONFIG_HOA_ORDER3; + } else { + return AVERROR_INVALIDDATA; + } + } else { + return AVERROR_INVALIDDATA; + } + + skip_bits(&gb, 2); + if (coding_profile != 1) { + bitrate_index = get_bits(&gb, 4); + if (bitrate_index < 0) { + return AVERROR_INVALIDDATA; + } + total_bitrate = ff_av3a_bitrate_map_table[channel_number_index].bitrate_table[bitrate_index]; + } + + skip_bits(&gb, 8); + + if (sampling_rate == 44100) { + payloud_bits = (int)floor(((float) (total_bitrate) / sampling_rate) * AV3A_AUDIO_FRAME_SIZE); + payload_bytes = (int)ceil((float)payloud_bits / 8); + } else { + payload_bytes = (int)ceil((((float) (total_bitrate) / sampling_rate) * AV3A_AUDIO_FRAME_SIZE) / 8); + } + + avio_seek(s->pb, -read_bytes, SEEK_CUR); + + return payload_bytes; +} + +static int av3a_probe(const AVProbeData *p) +{ + + uint16_t frame_sync_word; + uint16_t lval = ((uint16_t)(p->buf[0])); + uint16_t rval = ((uint16_t)(p->buf[1])); + frame_sync_word = ((lval << 8) | rval) >> 4; + + if (frame_sync_word == AV3A_AUDIO_SYNC_WORD && av_match_ext(p->filename, "av3a")) { + return AVPROBE_SCORE_MAX; + } + + return 0; +} + +static int av3a_read_header(AVFormatContext *s) +{ + int ret = 0; + uint8_t header[AV3A_MAX_NBYTES_HEADER]; + AVIOContext *pb = s->pb; + AVStream *stream = NULL; + Av3aFormatContext av3afmtctx; + AATFHeaderInfo hdf; + + if (!(stream = avformat_new_stream(s, NULL))) { + return AVERROR(ENOMEM); + } + + stream->start_time = 0; + ffstream(stream)->need_parsing = AVSTREAM_PARSE_FULL_RAW; + stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + stream->codecpar->codec_id = s->iformat->raw_codec_id; + stream->codecpar->codec_tag = MKTAG('a', 'v', '3', 'a'); + + if ((ret = avio_read(pb, header, AV3A_MAX_NBYTES_HEADER)) != AV3A_MAX_NBYTES_HEADER) { + return (ret < 0) ? ret : AVERROR_EOF; + } + + ret = av3a_read_aatf_frame_header(&hdf, header); + if (ret) { + return ret; + } + + /* stream parameters */ + stream->codecpar->format = hdf.sample_format; + stream->codecpar->bits_per_raw_sample = hdf.resolution; + stream->codecpar->bit_rate = hdf.total_bitrate; + stream->codecpar->sample_rate = (int) (hdf.sampling_rate); + stream->codecpar->frame_size = AV3A_AUDIO_FRAME_SIZE; + stream->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + stream->codecpar->ch_layout.nb_channels = hdf.total_channels; + + /* extradata */ + av3afmtctx.audio_codec_id = hdf.audio_codec_id; + av3afmtctx.sampling_frequency_index = hdf.sampling_frequency_index; + av3afmtctx.nn_type = hdf.nn_type; + av3afmtctx.content_type = hdf.content_type; + av3afmtctx.channel_number_index = hdf.channel_number_index; + av3afmtctx.number_objects = hdf.nb_objects; + av3afmtctx.hoa_order = hdf.hoa_order; + av3afmtctx.resolution_index = hdf.resolution_index; + av3afmtctx.total_bitrate_kbps = (int) (hdf.total_bitrate / 1000); + + if((ret = ff_alloc_extradata(stream->codecpar, sizeof(Av3aFormatContext))) < 0) { + return ret; + } + memcpy(stream->codecpar->extradata, &av3afmtctx, sizeof(Av3aFormatContext)); + + avio_seek(s->pb, -AV3A_MAX_NBYTES_HEADER, SEEK_CUR); + + return 0; +} + +static int av3a_read_packet(AVFormatContext *s, AVPacket *pkt) { + + int64_t pos; + int packet_size = 0; + int read_bytes = 0; + int ret = 0; + + if (!s->streams[0]->codecpar) { + return AVERROR(ENOMEM); + } + + if (avio_feof(s->pb)) { + return AVERROR_EOF; + } + pos = avio_tell(s->pb); + + if (!(packet_size = av3a_get_packet_size(s))) { + return AVERROR_EOF; + } + + if (packet_size < 0) { + return packet_size; + } + + ret = av_new_packet(pkt, packet_size); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", packet_size); + return ret; + } + + pkt->stream_index = 0; + pkt->pos = pos; + pkt->duration = s->streams[0]->codecpar->frame_size; + + read_bytes = avio_read(s->pb, pkt->data, packet_size); + if (read_bytes != packet_size) { + return (read_bytes < 0) ? read_bytes : AVERROR_EOF; + } + + return 0; +} + +const AVInputFormat ff_av3a_demuxer = { + .name = "av3a", + .long_name = NULL_IF_CONFIG_SMALL("Audio Vivid"), + .raw_codec_id = AV_CODEC_ID_AVS3DA, + .priv_data_size = sizeof(FFRawDemuxerContext), + .read_probe = av3a_probe, + .read_header = av3a_read_header, + .read_packet = av3a_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "av3a", + .mime_type = "audio/av3a", +}; diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index e74e2e8a89..9659e8ca2f 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -339,7 +339,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') }, /* mp4ra.org */ { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') }, /* mp4ra.org */ { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, /* MPEG-H 3D Audio bitstream */ - { AV_CODEC_ID_AVS3DA, MKTAG('a', 'v', '3', 'a') }, /* AVS3 Audio */ + { AV_CODEC_ID_AVS3DA, MKTAG('a', 'v', '3', 'a') }, { AV_CODEC_ID_NONE, 0 }, }; diff --git a/libavformat/mov.c b/libavformat/mov.c index 9151aa36cc..21507acce7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -64,6 +64,7 @@ #include "id3v1.h" #include "mov_chan.h" #include "replaygain.h" +#include "libavcodec/av3a.h" #if CONFIG_ZLIB #include @@ -7922,6 +7923,123 @@ static int mov_read_gnre(MOVContext *c, AVIOContext *pb, MOVAtom atom) } #endif +static int mov_read_dca3(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int ret = 0; + int i = 0; + AVStream *st = NULL; + GetBitContext gb; + uint8_t buffer[7]; + uint8_t audio_codec_id, sampling_frequency_index; + uint8_t nn_type, content_type, channel_number_index, number_objects; + uint8_t hoa_order, resolution_index, reserved; + int32_t bitrate_kbps; + int16_t nb_channels, nb_objects; + + nb_channels = 0; + nb_objects = 0; + + if (atom.size < 5) { + av_log(c->fc, AV_LOG_INFO, "Invalid dca3 box size %ld\n", atom.size); + return 0; + } + + init_get_bits8(&gb, buffer, sizeof(buffer)); + + if (c->fc->nb_streams < 1) { + return 0; + } + st = c->fc->streams[c->fc->nb_streams - 1]; + + ret = avio_read(pb, buffer, sizeof(buffer)); + if (ret < 0){ + return ret; + } + + audio_codec_id = get_bits(&gb, 4); + if (audio_codec_id != 2) { + av_log(c->fc, AV_LOG_INFO, "Invalid dca3 box size %ld\n", atom.size); + return AVERROR_INVALIDDATA; + } + + st->codecpar->frame_size = AV3A_AUDIO_FRAME_SIZE; + sampling_frequency_index = get_bits(&gb, 4); + if (sampling_frequency_index >= AV3A_SIZE_FS_TABLE) { + return AVERROR_INVALIDDATA; + } + st->codecpar->sample_rate = ff_av3a_sampling_rate_table[sampling_frequency_index]; + + nn_type = get_bits(&gb, 3); + reserved = get_bits(&gb, 1); + content_type = get_bits(&gb, 4); + + if (content_type == 0) { + channel_number_index = get_bits(&gb, 7); + reserved = get_bits(&gb, 1); + if (channel_number_index >= CHANNEL_CONFIG_UNKNOWN) { + return AVERROR_INVALIDDATA; + } + nb_channels = ff_av3a_channels_map_table[channel_number_index].channels; + } else if (content_type == 1) { + number_objects = get_bits(&gb, 7); + reserved = get_bits(&gb, 1); + nb_objects = number_objects; + } else if (content_type == 2) { + channel_number_index = get_bits(&gb, 7); + reserved = get_bits(&gb, 1); + number_objects = get_bits(&gb, 7); + reserved = get_bits(&gb, 1); + + if (channel_number_index >= CHANNEL_CONFIG_UNKNOWN) { + return AVERROR_INVALIDDATA; + } + nb_channels = ff_av3a_channels_map_table[channel_number_index].channels; + nb_objects = number_objects; + } else if (content_type == 3) { + hoa_order = get_bits(&gb , 4); + if (hoa_order > 3) { + return AVERROR_INVALIDDATA; + } + nb_channels = (hoa_order + 1) * (hoa_order + 1); + } else { + av_log(c->fc, AV_LOG_INFO, "Invalid content_type value %ld\n", content_type); + return AVERROR_INVALIDDATA; + } + + bitrate_kbps = get_bits(&gb, 16); + st->codecpar->bit_rate = bitrate_kbps * 1000; + + resolution_index = get_bits(&gb, 2); + if (resolution_index >= AV3A_SIZE_RESOLUTION_TABLE) { + return AVERROR_INVALIDDATA; + } + st->codecpar->format = ff_av3a_sample_format_map_table[resolution_index].sample_format; + st->codecpar->bits_per_raw_sample = ff_av3a_sample_format_map_table[resolution_index].resolution; + + av_channel_layout_uninit(&st->codecpar->channel_layout); + if (content_type != 3) { + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_CUSTOM; + st->codecpar->ch_layout.nb_channels = (nb_channels + nb_objects); + st->codecpar->ch_layout.u.map = av_calloc(st->codecpar->ch_layout.nb_channels, + sizeof(*st->codecpar->ch_layout.u.map)); + + if (content_type != 1) { + for(i = 0; i < nb_channels; i ++) { + st->codecpar->ch_layout.u.map[i].id = ff_av3a_channels_map_table[channel_number_index].channel_layout[i]; + } + } + + for (i = nb_channels; i < st->codecpar->ch_layout.nb_channels; i++) { + st->codecpar->ch_layout.u.map[i].id = AV3A_CH_AUDIO_OBJECT; + } + } else { + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC; + st->codecpar->ch_layout.nb_channels = nb_channels; + } + + return 0; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_aclr }, { MKTAG('A','P','R','G'), mov_read_avid }, @@ -8037,6 +8155,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { #ifdef OHOS_TIMED_META_TRACK { MKTAG('c','d','s','c'), mov_read_cdsc }, #endif +{ MKTAG('d','c','a','3'), mov_read_dca3 }, { 0, NULL } }; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 206bc95070..792751bda8 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -899,6 +899,78 @@ static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } +static int mov_write_dca3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + uint8_t buffer[7]; + PutBitContext pb_dca3; + int16_t audio_codec_id, sampling_frequency_index, nn_type, content_type; + int16_t channel_number_index, number_objects, hoa_order, resolution_index; + int32_t bitrate_kbps; + + if (track->par->extradata_size < 10) { + av_log(s, AV_LOG_WARNING, "Can not write dca3 box\n"); + return 0; + } + + avio_wb32(pb, 0); /* Size */ + ffio_wfourcc(pb, "dca3"); /* Type */ + + init_put_bits(&pb_dca3, buffer, 7); + + audio_codec_id = AV_RB8(track->par->extradata + 0); + sampling_frequency_index = AV_RB8(track->par->extradata + 1); + nn_type = AV_RB8(track->par->extradata + 2); + content_type = AV_RB8(track->par->extradata + 3); + channel_number_index = AV_RB8(track->par->extradata + 4); + number_objects = AV_RB8(track->par->extradata + 5); + hoa_order = AV_RB8(track->par->extradata + 6); + resolution_index = AV_RB8(track->par->extradata + 7); + bitrate_kbps = AV_RB16(track->par->extradata + 8); + + if (audio_codec_id != 2) { + av_log(s, AV_LOG_ERROR, "Not support audio codec id %d\n", audio_codec_id); + return AVERROR_INVALIDDATA; + } + put_bits(&pb_dca3, 4, audio_codec_id); + put_bits(&pb_dca3, 4, sampling_frequency_index); + + put_bits(&pb_dca3, 3, nn_type); + put_bits(&pb_dca3, 1, 0); /* reserved */ + put_bits(&pb_dca3, 4, content_type); + + if (content_type == 0) { + put_bits(&pb_dca3, 7, channel_number_index); + put_bits(&pb_dca3, 1, 0); /* reserved */ + } else if (content_type == 1){ + put_bits(&pb_dca3, 7, number_objects); + put_bits(&pb_dca3, 1, 0); /* reserved */ + } else if (content_type == 2){ + put_bits(&pb_dca3, 7, channel_number_index); + put_bits(&pb_dca3, 1, 0); /* reserved */ + put_bits(&pb_dca3, 7, number_objects); + put_bits(&pb_dca3, 1, 0); /* reserved */ + } else if (content_type == 3) { + put_bits(&pb_dca3, 4, hoa_order); + } else { + return AVERROR_INVALIDDATA; + } + + put_bits(&pb_dca3, 16, bitrate_kbps); + put_bits(&pb_dca3, 2, resolution_index); + + if (content_type == 3) { + put_bits(&pb_dca3, 2, 0); /* reserved */ + } else { + put_bits(&pb_dca3, 6, 0); /* reserved */ + } + + flush_put_bits(&pb_dca3); + avio_write(pb, buffer, sizeof(buffer)); + + return update_size(pb, pos); +} + static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { uint32_t layout_tag, bitmap, *channel_desc; @@ -1258,7 +1330,8 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex } else { /* reserved for mp4/3gp */ if (track->par->codec_id == AV_CODEC_ID_FLAC || track->par->codec_id == AV_CODEC_ID_ALAC || - track->par->codec_id == AV_CODEC_ID_OPUS) { + track->par->codec_id == AV_CODEC_ID_OPUS || + track->par->codec_id == AV_CODEC_ID_AVS3DA) { avio_wb16(pb, track->par->ch_layout.nb_channels); } else { avio_wb16(pb, 2); @@ -1326,6 +1399,8 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex ret = mov_write_dops_tag(s, pb, track); else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) ret = mov_write_dmlp_tag(s, pb, track); + else if (track->par->codec_id == AV_CODEC_ID_AVS3DA) + ret = mov_write_dca3_tag(s, pb, track); else if (track->vos_len > 0) ret = mov_write_glbl_tag(pb, track); @@ -8277,6 +8352,7 @@ static const AVCodecTag codec_mp4_tags[] = { #ifdef OHOS_TIMED_META_TRACK { AV_CODEC_ID_FFMETADATA, MKTAG('c', 'd', 's', 'c') }, #endif + { AV_CODEC_ID_AVS3DA, MKTAG('a', 'v', '3', 'a') }, { AV_CODEC_ID_NONE, 0 }, }; #if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index c0e26181e5..886a4726f2 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1408,7 +1408,7 @@ static const StreamType ISO_types[] = { { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, { 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, { 0xd4, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS3 }, - { 0xd5, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AVS3DA }, /* avs3 audio */ + { 0xd5, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AVS3DA }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; @@ -1463,7 +1463,6 @@ static const StreamType REGD_types[] = { { MKTAG('I', 'D', '3', ' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 }, { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS }, - { MKTAG('a', 'v', '3', 'a'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AVS3DA}, /* AVS3 Audio descriptor Tag */ { 0 }, }; diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h index 6de47f7cb8..eb5d7b54e3 100644 --- a/libavformat/mpegts.h +++ b/libavformat/mpegts.h @@ -133,6 +133,7 @@ #define STREAM_TYPE_VIDEO_AVS3 0xd4 #define STREAM_TYPE_VIDEO_VC1 0xea #define STREAM_TYPE_VIDEO_DIRAC 0xd1 +#define STREAM_TYPE_AUDIO_AV3A 0xd5 #define STREAM_TYPE_AUDIO_AC3 0x81 #define STREAM_TYPE_AUDIO_DTS 0x82 diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 2dd8a20d85..36477cb70e 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -433,6 +433,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) stream_type = STREAM_TYPE_PRIVATE_DATA; } break; + case AV_CODEC_ID_AVS3DA: + stream_type = STREAM_TYPE_AUDIO_AV3A; + break; default: av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, "Stream %d, codec %s, is muxed as a private data stream " @@ -441,6 +444,7 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) stream_type = STREAM_TYPE_PRIVATE_DATA; break; } + return stream_type; } diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 26099cb1c1..983b3b7df8 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -131,6 +131,20 @@ const AVOutputFormat ff_aptx_hd_muxer = { }; #endif +#if CONFIG_AV3A_MUXER +const AVOutputFormat ff_av3a_muxer = { + .name = "av3a", + .long_name = NULL_IF_CONFIG_SMALL("Audio Vivid"), + .mime_type = "audio/av3a", + .extensions = "av3a", + .audio_codec = AV_CODEC_ID_AVS3DA, + .video_codec = AV_CODEC_ID_NONE, + .init = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_AVS2_MUXER const AVOutputFormat ff_avs2_muxer = { .name = "avs2", diff --git a/ohos_config.sh b/ohos_config.sh index cd7e9ce554..94db981de9 100755 --- a/ohos_config.sh +++ b/ohos_config.sh @@ -50,8 +50,8 @@ FF_CONFIG_OPTIONS=" --disable-bzlib --disable-lzma --disable-vulkan - --enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv,mpegps,asf,asf_o,srt,h264,webvtt - --enable-muxer=mp4,h264,ipod,amr,mpegts,mp3,wav,flac + --enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv,mpegps,asf,asf_o,srt,h264,webvtt,av3a + --enable-muxer=mp4,h264,ipod,amr,mpegts,mp3,wav,flac,av3a --enable-parser=h263,h264,mpeg4video,vp8,vp9,mpegvideo --enable-parser=mpegaudio,aac,aac_latm,av3a,amr,opus --enable-decoder=h263,h264,mpeg2video,mpeg4,vp8,vp9 @@ -144,8 +144,8 @@ FF_CONFIG_OPTIONS=" --disable-sdl2 --disable-bzlib --disable-lzma - --enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv,mpegps,asf,asf_o,srt,h264,webvtt - --enable-muxer=mp4,h264,ipod,amr,mpegts,mp3,wav,flac + --enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv,mpegps,asf,asf_o,srt,h264,webvtt,av3a + --enable-muxer=mp4,h264,ipod,amr,mpegts,mp3,wav,flac,av3a --enable-parser=h263,h264,mpeg4video,vp8,vp9,mpegvideo --enable-parser=mpegaudio,aac,aac_latm,av3a,amr,opus --enable-decoder=h263,h264,mpeg2video,mpeg4,vp8,vp9