283 lines
8.1 KiB
C++
283 lines
8.1 KiB
C++
|
/*
|
||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#include "api/audio/channel_layout.h"
|
||
|
|
||
|
#include <stddef.h>
|
||
|
|
||
|
#include "rtc_base/arraysize.h"
|
||
|
#include "rtc_base/checks.h"
|
||
|
#include "rtc_base/logging.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
static const int kLayoutToChannels[] = {
|
||
|
0, // CHANNEL_LAYOUT_NONE
|
||
|
0, // CHANNEL_LAYOUT_UNSUPPORTED
|
||
|
1, // CHANNEL_LAYOUT_MONO
|
||
|
2, // CHANNEL_LAYOUT_STEREO
|
||
|
3, // CHANNEL_LAYOUT_2_1
|
||
|
3, // CHANNEL_LAYOUT_SURROUND
|
||
|
4, // CHANNEL_LAYOUT_4_0
|
||
|
4, // CHANNEL_LAYOUT_2_2
|
||
|
4, // CHANNEL_LAYOUT_QUAD
|
||
|
5, // CHANNEL_LAYOUT_5_0
|
||
|
6, // CHANNEL_LAYOUT_5_1
|
||
|
5, // CHANNEL_LAYOUT_5_0_BACK
|
||
|
6, // CHANNEL_LAYOUT_5_1_BACK
|
||
|
7, // CHANNEL_LAYOUT_7_0
|
||
|
8, // CHANNEL_LAYOUT_7_1
|
||
|
8, // CHANNEL_LAYOUT_7_1_WIDE
|
||
|
2, // CHANNEL_LAYOUT_STEREO_DOWNMIX
|
||
|
3, // CHANNEL_LAYOUT_2POINT1
|
||
|
4, // CHANNEL_LAYOUT_3_1
|
||
|
5, // CHANNEL_LAYOUT_4_1
|
||
|
6, // CHANNEL_LAYOUT_6_0
|
||
|
6, // CHANNEL_LAYOUT_6_0_FRONT
|
||
|
6, // CHANNEL_LAYOUT_HEXAGONAL
|
||
|
7, // CHANNEL_LAYOUT_6_1
|
||
|
7, // CHANNEL_LAYOUT_6_1_BACK
|
||
|
7, // CHANNEL_LAYOUT_6_1_FRONT
|
||
|
7, // CHANNEL_LAYOUT_7_0_FRONT
|
||
|
8, // CHANNEL_LAYOUT_7_1_WIDE_BACK
|
||
|
8, // CHANNEL_LAYOUT_OCTAGONAL
|
||
|
0, // CHANNEL_LAYOUT_DISCRETE
|
||
|
3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC
|
||
|
5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE
|
||
|
0, // CHANNEL_LAYOUT_BITSTREAM
|
||
|
};
|
||
|
|
||
|
// The channel orderings for each layout as specified by FFmpeg. Each value
|
||
|
// represents the index of each channel in each layout. Values of -1 mean the
|
||
|
// channel at that index is not used for that layout. For example, the left side
|
||
|
// surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because
|
||
|
// the order is L, R, C, LFE, LS, RS), so
|
||
|
// kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4;
|
||
|
static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = {
|
||
|
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||
|
|
||
|
// CHANNEL_LAYOUT_NONE
|
||
|
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_UNSUPPORTED
|
||
|
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_MONO
|
||
|
{-1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_STEREO
|
||
|
{0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_2_1
|
||
|
{0, 1, -1, -1, -1, -1, -1, -1, 2, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_SURROUND
|
||
|
{0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_4_0
|
||
|
{0, 1, 2, -1, -1, -1, -1, -1, 3, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_2_2
|
||
|
{0, 1, -1, -1, -1, -1, -1, -1, -1, 2, 3},
|
||
|
|
||
|
// CHANNEL_LAYOUT_QUAD
|
||
|
{0, 1, -1, -1, 2, 3, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_5_0
|
||
|
{0, 1, 2, -1, -1, -1, -1, -1, -1, 3, 4},
|
||
|
|
||
|
// CHANNEL_LAYOUT_5_1
|
||
|
{0, 1, 2, 3, -1, -1, -1, -1, -1, 4, 5},
|
||
|
|
||
|
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||
|
|
||
|
// CHANNEL_LAYOUT_5_0_BACK
|
||
|
{0, 1, 2, -1, 3, 4, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_5_1_BACK
|
||
|
{0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_7_0
|
||
|
{0, 1, 2, -1, 5, 6, -1, -1, -1, 3, 4},
|
||
|
|
||
|
// CHANNEL_LAYOUT_7_1
|
||
|
{0, 1, 2, 3, 6, 7, -1, -1, -1, 4, 5},
|
||
|
|
||
|
// CHANNEL_LAYOUT_7_1_WIDE
|
||
|
{0, 1, 2, 3, -1, -1, 6, 7, -1, 4, 5},
|
||
|
|
||
|
// CHANNEL_LAYOUT_STEREO_DOWNMIX
|
||
|
{0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_2POINT1
|
||
|
{0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_3_1
|
||
|
{0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_4_1
|
||
|
{0, 1, 2, 4, -1, -1, -1, -1, 3, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_6_0
|
||
|
{0, 1, 2, -1, -1, -1, -1, -1, 5, 3, 4},
|
||
|
|
||
|
// CHANNEL_LAYOUT_6_0_FRONT
|
||
|
{0, 1, -1, -1, -1, -1, 4, 5, -1, 2, 3},
|
||
|
|
||
|
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||
|
|
||
|
// CHANNEL_LAYOUT_HEXAGONAL
|
||
|
{0, 1, 2, -1, 3, 4, -1, -1, 5, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_6_1
|
||
|
{0, 1, 2, 3, -1, -1, -1, -1, 6, 4, 5},
|
||
|
|
||
|
// CHANNEL_LAYOUT_6_1_BACK
|
||
|
{0, 1, 2, 3, 4, 5, -1, -1, 6, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_6_1_FRONT
|
||
|
{0, 1, -1, 6, -1, -1, 4, 5, -1, 2, 3},
|
||
|
|
||
|
// CHANNEL_LAYOUT_7_0_FRONT
|
||
|
{0, 1, 2, -1, -1, -1, 5, 6, -1, 3, 4},
|
||
|
|
||
|
// CHANNEL_LAYOUT_7_1_WIDE_BACK
|
||
|
{0, 1, 2, 3, 4, 5, 6, 7, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_OCTAGONAL
|
||
|
{0, 1, 2, -1, 5, 6, -1, -1, 7, 3, 4},
|
||
|
|
||
|
// CHANNEL_LAYOUT_DISCRETE
|
||
|
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC
|
||
|
{0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// CHANNEL_LAYOUT_4_1_QUAD_SIDE
|
||
|
{0, 1, -1, 4, -1, -1, -1, -1, -1, 2, 3},
|
||
|
|
||
|
// CHANNEL_LAYOUT_BITSTREAM
|
||
|
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||
|
|
||
|
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||
|
};
|
||
|
|
||
|
int ChannelLayoutToChannelCount(ChannelLayout layout) {
|
||
|
RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kLayoutToChannels));
|
||
|
RTC_DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels);
|
||
|
return kLayoutToChannels[layout];
|
||
|
}
|
||
|
|
||
|
// Converts a channel count into a channel layout.
|
||
|
ChannelLayout GuessChannelLayout(int channels) {
|
||
|
switch (channels) {
|
||
|
case 1:
|
||
|
return CHANNEL_LAYOUT_MONO;
|
||
|
case 2:
|
||
|
return CHANNEL_LAYOUT_STEREO;
|
||
|
case 3:
|
||
|
return CHANNEL_LAYOUT_SURROUND;
|
||
|
case 4:
|
||
|
return CHANNEL_LAYOUT_QUAD;
|
||
|
case 5:
|
||
|
return CHANNEL_LAYOUT_5_0;
|
||
|
case 6:
|
||
|
return CHANNEL_LAYOUT_5_1;
|
||
|
case 7:
|
||
|
return CHANNEL_LAYOUT_6_1;
|
||
|
case 8:
|
||
|
return CHANNEL_LAYOUT_7_1;
|
||
|
default:
|
||
|
RTC_DLOG(LS_WARNING) << "Unsupported channel count: " << channels;
|
||
|
}
|
||
|
return CHANNEL_LAYOUT_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
int ChannelOrder(ChannelLayout layout, Channels channel) {
|
||
|
RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings));
|
||
|
RTC_DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0]));
|
||
|
return kChannelOrderings[layout][channel];
|
||
|
}
|
||
|
|
||
|
const char* ChannelLayoutToString(ChannelLayout layout) {
|
||
|
switch (layout) {
|
||
|
case CHANNEL_LAYOUT_NONE:
|
||
|
return "NONE";
|
||
|
case CHANNEL_LAYOUT_UNSUPPORTED:
|
||
|
return "UNSUPPORTED";
|
||
|
case CHANNEL_LAYOUT_MONO:
|
||
|
return "MONO";
|
||
|
case CHANNEL_LAYOUT_STEREO:
|
||
|
return "STEREO";
|
||
|
case CHANNEL_LAYOUT_2_1:
|
||
|
return "2.1";
|
||
|
case CHANNEL_LAYOUT_SURROUND:
|
||
|
return "SURROUND";
|
||
|
case CHANNEL_LAYOUT_4_0:
|
||
|
return "4.0";
|
||
|
case CHANNEL_LAYOUT_2_2:
|
||
|
return "QUAD_SIDE";
|
||
|
case CHANNEL_LAYOUT_QUAD:
|
||
|
return "QUAD";
|
||
|
case CHANNEL_LAYOUT_5_0:
|
||
|
return "5.0";
|
||
|
case CHANNEL_LAYOUT_5_1:
|
||
|
return "5.1";
|
||
|
case CHANNEL_LAYOUT_5_0_BACK:
|
||
|
return "5.0_BACK";
|
||
|
case CHANNEL_LAYOUT_5_1_BACK:
|
||
|
return "5.1_BACK";
|
||
|
case CHANNEL_LAYOUT_7_0:
|
||
|
return "7.0";
|
||
|
case CHANNEL_LAYOUT_7_1:
|
||
|
return "7.1";
|
||
|
case CHANNEL_LAYOUT_7_1_WIDE:
|
||
|
return "7.1_WIDE";
|
||
|
case CHANNEL_LAYOUT_STEREO_DOWNMIX:
|
||
|
return "STEREO_DOWNMIX";
|
||
|
case CHANNEL_LAYOUT_2POINT1:
|
||
|
return "2POINT1";
|
||
|
case CHANNEL_LAYOUT_3_1:
|
||
|
return "3.1";
|
||
|
case CHANNEL_LAYOUT_4_1:
|
||
|
return "4.1";
|
||
|
case CHANNEL_LAYOUT_6_0:
|
||
|
return "6.0";
|
||
|
case CHANNEL_LAYOUT_6_0_FRONT:
|
||
|
return "6.0_FRONT";
|
||
|
case CHANNEL_LAYOUT_HEXAGONAL:
|
||
|
return "HEXAGONAL";
|
||
|
case CHANNEL_LAYOUT_6_1:
|
||
|
return "6.1";
|
||
|
case CHANNEL_LAYOUT_6_1_BACK:
|
||
|
return "6.1_BACK";
|
||
|
case CHANNEL_LAYOUT_6_1_FRONT:
|
||
|
return "6.1_FRONT";
|
||
|
case CHANNEL_LAYOUT_7_0_FRONT:
|
||
|
return "7.0_FRONT";
|
||
|
case CHANNEL_LAYOUT_7_1_WIDE_BACK:
|
||
|
return "7.1_WIDE_BACK";
|
||
|
case CHANNEL_LAYOUT_OCTAGONAL:
|
||
|
return "OCTAGONAL";
|
||
|
case CHANNEL_LAYOUT_DISCRETE:
|
||
|
return "DISCRETE";
|
||
|
case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
|
||
|
return "STEREO_AND_KEYBOARD_MIC";
|
||
|
case CHANNEL_LAYOUT_4_1_QUAD_SIDE:
|
||
|
return "4.1_QUAD_SIDE";
|
||
|
case CHANNEL_LAYOUT_BITSTREAM:
|
||
|
return "BITSTREAM";
|
||
|
}
|
||
|
RTC_DCHECK_NOTREACHED() << "Invalid channel layout provided: " << layout;
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
} // namespace webrtc
|