History

avutil/channel_layout: add av_channel_layout_retype()

Marton Balint committed 2 years ago

Commit 66386bf1 parent 4569b864 files · +150 −1Browse files

Unified · Split

4 files
  1. doc/APIchanges +3 −0
  2. libavutil/channel_layout.c +106 −0
  3. libavutil/channel_layout.h +40 −0
  4. libavutil/version.h +1 −1
doc/APIchanges+3−0
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 · 1 unmodified line
2 2
3API changes, most recent first:3API changes, most recent first:
4 4
52024-02-xx - xxxxxxxxxx - lavu 58.38.100 - channel_layout.h
6 Add av_channel_layout_retype().
7
52024-02-xx - xxxxxxxxxx - lavu 58.37.100 - channel_layout.h82024-02-xx - xxxxxxxxxx - lavu 58.37.100 - channel_layout.h
6 Add av_channel_layout_custom_init().9 Add av_channel_layout_custom_init().
7 10
libavutil/channel_layout.c+106−0
@@ -1036,3 +1036,109 @@ uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, · 1035 unmodified lines
1036 1036
1037 return ret;1037 return ret;
1038}1038}
1039
1040static int64_t masked_description(AVChannelLayout *channel_layout, int start_channel)
1041{
1042 uint64_t mask = 0;
1043 for (int i = start_channel; i < channel_layout->nb_channels; i++) {
1044 enum AVChannel ch = channel_layout->u.map[i].id;
1045 if (ch >= 0 && ch < 63 && mask < (1ULL << ch))
1046 mask |= (1ULL << ch);
1047 else
1048 return AVERROR(EINVAL);
1049 }
1050 return mask;
1051}
1052
1053static int has_channel_names(AVChannelLayout *channel_layout)
1054{
1055 if (channel_layout->order != AV_CHANNEL_ORDER_CUSTOM)
1056 return 0;
1057 for (int i = 0; i < channel_layout->nb_channels; i++)
1058 if (channel_layout->u.map[i].name[0])
1059 return 1;
1060 return 0;
1061}
1062
1063int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags)
1064{
1065 int allow_lossy = !(flags & AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS);
1066 int lossy;
1067
1068 if (!av_channel_layout_check(channel_layout))
1069 return AVERROR(EINVAL);
1070
1071 if (channel_layout->order == order)
1072 return 0;
1073
1074 switch (order) {
1075 case AV_CHANNEL_ORDER_UNSPEC: {
1076 int nb_channels = channel_layout->nb_channels;
1077 if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
1078 lossy = 0;
1079 for (int i = 0; i < nb_channels; i++) {
1080 if (channel_layout->u.map[i].id != AV_CHAN_UNKNOWN || channel_layout->u.map[i].name[0]) {
1081 lossy = 1;
1082 break;
1083 }
1084 }
1085 } else {
1086 lossy = 1;
1087 }
1088 if (!lossy || allow_lossy) {
1089 av_channel_layout_uninit(channel_layout);
1090 channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
1091 channel_layout->nb_channels = nb_channels;
1092 return lossy;
1093 }
1094 return AVERROR(ENOSYS);
1095 }
1096 case AV_CHANNEL_ORDER_NATIVE:
1097 if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
1098 int64_t mask = masked_description(channel_layout, 0);
1099 if (mask < 0)
1100 return AVERROR(ENOSYS);
1101 lossy = has_channel_names(channel_layout);
1102 if (!lossy || allow_lossy) {
1103 av_channel_layout_uninit(channel_layout);
1104 av_channel_layout_from_mask(channel_layout, mask);
1105 return lossy;
1106 }
1107 }
1108 return AVERROR(ENOSYS);
1109 case AV_CHANNEL_ORDER_CUSTOM: {
1110 AVChannelLayout custom = { 0 };
1111 int ret = av_channel_layout_custom_init(&custom, channel_layout->nb_channels);
1112 if (ret < 0)
1113 return ret;
1114 if (channel_layout->order != AV_CHANNEL_ORDER_UNSPEC)
1115 for (int i = 0; i < channel_layout->nb_channels; i++)
1116 custom.u.map[i].id = av_channel_layout_channel_from_index(channel_layout, i);
1117 av_channel_layout_uninit(channel_layout);
1118 *channel_layout = custom;
1119 return 0;
1120 }
1121 case AV_CHANNEL_ORDER_AMBISONIC:
1122 if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
1123 int64_t mask;
1124 int nb_channels = channel_layout->nb_channels;
1125 int order = ambisonic_order(channel_layout);
1126 if (order < 0)
1127 return AVERROR(ENOSYS);
1128 mask = masked_description(channel_layout, (order + 1) * (order + 1));
1129 if (mask < 0)
1130 return AVERROR(ENOSYS);
1131 lossy = has_channel_names(channel_layout);
1132 if (!lossy || allow_lossy) {
1133 av_channel_layout_uninit(channel_layout);
1134 channel_layout->order = AV_CHANNEL_ORDER_AMBISONIC;
1135 channel_layout->nb_channels = nb_channels;
1136 channel_layout->u.mask = mask;
1137 return lossy;
1138 }
1139 }
1140 return AVERROR(ENOSYS);
1141 default:
1142 return AVERROR(EINVAL);
1143 }
1144}
libavutil/channel_layout.h+40−0
@@ -821,6 +821,46 @@ int av_channel_layout_check(const AVChannelLayout *channel_layout); · 820 unmodified lines
821 */821 */
822int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);822int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);
823 823
824/**
825 * The conversion must be lossless.
826 */
827#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS (1 << 0)
828
829/**
830 * Change the AVChannelOrder of a channel layout.
831 *
832 * Change of AVChannelOrder can be either lossless or lossy. In case of a
833 * lossless conversion all the channel designations and the associated channel
834 * names (if any) are kept. On a lossy conversion the channel names and channel
835 * designations might be lost depending on the capabilities of the desired
836 * AVChannelOrder. Note that some conversions are simply not possible in which
837 * case this function returns AVERROR(ENOSYS).
838 *
839 * The following conversions are supported:
840 *
841 * Any -> Custom : Always possible, always lossless.
842 * Any -> Unspecified: Always possible, lossless if channel designations
843 * are all unknown and channel names are not used, lossy otherwise.
844 * Custom -> Ambisonic : Possible if it contains ambisonic channels with
845 * optional non-diegetic channels in the end. Lossy if the channels have
846 * custom names, lossless otherwise.
847 * Custom -> Native : Possible if it contains native channels in native
848 * order. Lossy if the channels have custom names, lossless otherwise.
849 *
850 * On error this function keeps the original channel layout untouched.
851 *
852 * @param channel_layout channel layout which will be changed
853 * @param order the desired channel layout order
854 * @param flags a combination of AV_CHANNEL_LAYOUT_RETYPE_FLAG_* constants
855 * @return 0 if the conversion was successful and lossless or if the channel
856 * layout was already in the desired order
857 * >0 if the conversion was successful but lossy
858 * AVERROR(ENOSYS) if the conversion was not possible (or would be
859 * lossy and AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS was specified)
860 * AVERROR(EINVAL), AVERROR(ENOMEM) on error
861 */
862int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags);
863
824/**864/**
825 * @}865 * @}
826 */866 */
libavutil/version.h+1−1
@@ -79,7 +79,7 @@ · 78 unmodified lines
79 */79 */
80 80
81#define LIBAVUTIL_VERSION_MAJOR 5881#define LIBAVUTIL_VERSION_MAJOR 58
82#define LIBAVUTIL_VERSION_MINOR 3782#define LIBAVUTIL_VERSION_MINOR 38
83#define LIBAVUTIL_VERSION_MICRO 10083#define LIBAVUTIL_VERSION_MICRO 100
84 84
85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \85#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t