1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "ffmpeg_converter.h"
16 #include <vector>
17 namespace {
18 constexpr int US_PER_SECOND = 1000000;
19 }
20 namespace OHOS {
21 namespace MediaAVCodec {
22 // ffmpeg channel layout to histreamer channel layout
23 const std::vector<std::pair<AudioChannelLayout, uint64_t>> g_toFFMPEGChannelLayout = {
24 {AudioChannelLayout::MONO, AV_CH_LAYOUT_MONO},
25 {AudioChannelLayout::STEREO, AV_CH_LAYOUT_STEREO},
26 {AudioChannelLayout::CH_2POINT1, AV_CH_LAYOUT_2POINT1},
27 {AudioChannelLayout::CH_2_1, AV_CH_LAYOUT_2_1},
28 {AudioChannelLayout::SURROUND, AV_CH_LAYOUT_SURROUND},
29 {AudioChannelLayout::CH_3POINT1, AV_CH_LAYOUT_3POINT1},
30 {AudioChannelLayout::CH_4POINT0, AV_CH_LAYOUT_4POINT0},
31 {AudioChannelLayout::CH_4POINT1, AV_CH_LAYOUT_4POINT1},
32 {AudioChannelLayout::CH_2_2, AV_CH_LAYOUT_2_2},
33 {AudioChannelLayout::QUAD, AV_CH_LAYOUT_QUAD},
34 {AudioChannelLayout::CH_5POINT0, AV_CH_LAYOUT_5POINT0},
35 {AudioChannelLayout::CH_5POINT1, AV_CH_LAYOUT_5POINT1},
36 {AudioChannelLayout::CH_5POINT0_BACK, AV_CH_LAYOUT_5POINT0_BACK},
37 {AudioChannelLayout::CH_5POINT1_BACK, AV_CH_LAYOUT_5POINT1_BACK},
38 {AudioChannelLayout::CH_6POINT0, AV_CH_LAYOUT_6POINT0},
39 {AudioChannelLayout::CH_6POINT0_FRONT, AV_CH_LAYOUT_6POINT0_FRONT},
40 {AudioChannelLayout::HEXAGONAL, AV_CH_LAYOUT_HEXAGONAL},
41 {AudioChannelLayout::CH_6POINT1, AV_CH_LAYOUT_6POINT1},
42 {AudioChannelLayout::CH_6POINT1_BACK, AV_CH_LAYOUT_6POINT1_BACK},
43 {AudioChannelLayout::CH_6POINT1_FRONT, AV_CH_LAYOUT_6POINT1_FRONT},
44 {AudioChannelLayout::CH_7POINT0, AV_CH_LAYOUT_7POINT0},
45 {AudioChannelLayout::CH_7POINT0_FRONT, AV_CH_LAYOUT_7POINT0_FRONT},
46 {AudioChannelLayout::CH_7POINT1, AV_CH_LAYOUT_7POINT1},
47 {AudioChannelLayout::CH_7POINT1_WIDE, AV_CH_LAYOUT_7POINT1_WIDE},
48 {AudioChannelLayout::CH_7POINT1_WIDE_BACK, AV_CH_LAYOUT_7POINT1_WIDE_BACK},
49 {AudioChannelLayout::OCTAGONAL, AV_CH_LAYOUT_OCTAGONAL},
50 {AudioChannelLayout::HEXADECAGONAL, AV_CH_LAYOUT_HEXADECAGONAL},
51 {AudioChannelLayout::STEREO_DOWNMIX, AV_CH_LAYOUT_STEREO_DOWNMIX},
52 };
53
54 const std::vector<std::pair<AVSampleFormat, AudioSampleFormat>> g_pFfSampleFmtMap = {
55 {AVSampleFormat::AV_SAMPLE_FMT_U8, AudioSampleFormat::SAMPLE_U8},
56 {AVSampleFormat::AV_SAMPLE_FMT_S16, AudioSampleFormat::SAMPLE_S16LE},
57 {AVSampleFormat::AV_SAMPLE_FMT_S32, AudioSampleFormat::SAMPLE_S32LE},
58 {AVSampleFormat::AV_SAMPLE_FMT_FLT, AudioSampleFormat::SAMPLE_F32LE},
59 {AVSampleFormat::AV_SAMPLE_FMT_U8P, AudioSampleFormat::SAMPLE_U8P},
60 {AVSampleFormat::AV_SAMPLE_FMT_S16P, AudioSampleFormat::SAMPLE_S16P},
61 {AVSampleFormat::AV_SAMPLE_FMT_S32P, AudioSampleFormat::SAMPLE_S32P},
62 {AVSampleFormat::AV_SAMPLE_FMT_FLTP, AudioSampleFormat::SAMPLE_F32P},
63 };
64
65 // align with player framework capability.
66 const std::vector<std::pair<AVCodecID, AudioSampleFormat>> g_pFfCodeIDToSampleFmtMap = {
67 {AVCodecID::AV_CODEC_ID_PCM_U8, AudioSampleFormat::SAMPLE_U8},
68 {AVCodecID::AV_CODEC_ID_PCM_S16LE, AudioSampleFormat::SAMPLE_S16LE},
69 {AVCodecID::AV_CODEC_ID_PCM_S24LE, AudioSampleFormat::SAMPLE_S24LE},
70 {AVCodecID::AV_CODEC_ID_PCM_S32LE, AudioSampleFormat::SAMPLE_S32LE},
71 {AVCodecID::AV_CODEC_ID_PCM_F32LE, AudioSampleFormat::SAMPLE_F32LE},
72 };
73
74 const std::vector<std::pair<AudioChannelLayout, std::string_view>> g_ChannelLayoutToString = {
75 {AudioChannelLayout::MONO, "MONO"},
76 {AudioChannelLayout::STEREO, "STEREO"},
77 {AudioChannelLayout::CH_2POINT1, "2POINT1"},
78 {AudioChannelLayout::CH_2_1, "CH_2_1"},
79 {AudioChannelLayout::SURROUND, "SURROUND"},
80 {AudioChannelLayout::CH_3POINT1, "3POINT1"},
81 {AudioChannelLayout::CH_4POINT0, "4POINT0"},
82 {AudioChannelLayout::CH_4POINT1, "4POINT1"},
83 {AudioChannelLayout::CH_2_2, "CH_2_2"},
84 {AudioChannelLayout::QUAD, "QUAD"},
85 {AudioChannelLayout::CH_5POINT0, "5POINT0"},
86 {AudioChannelLayout::CH_5POINT1, "5POINT1"},
87 {AudioChannelLayout::CH_5POINT0_BACK, "5POINT0_BACK"},
88 {AudioChannelLayout::CH_5POINT1_BACK, "5POINT1_BACK"},
89 {AudioChannelLayout::CH_6POINT0, "6POINT0"},
90 {AudioChannelLayout::CH_6POINT0_FRONT, "6POINT0_FRONT"},
91 {AudioChannelLayout::HEXAGONAL, "HEXAGONAL"},
92 {AudioChannelLayout::CH_6POINT1, "6POINT1"},
93 {AudioChannelLayout::CH_6POINT1_BACK, "6POINT1_BACK"},
94 {AudioChannelLayout::CH_6POINT1_FRONT, "6POINT1_FRONT"},
95 {AudioChannelLayout::CH_7POINT0, "7POINT0"},
96 {AudioChannelLayout::CH_7POINT0_FRONT, "7POINT0_FRONT"},
97 {AudioChannelLayout::CH_7POINT1, "7POINT1"},
98 {AudioChannelLayout::CH_7POINT1_WIDE, "7POINT1_WIDE"},
99 {AudioChannelLayout::CH_7POINT1_WIDE_BACK, "7POINT1_WIDE_BACK"},
100 {AudioChannelLayout::OCTAGONAL, "OCTAGONAL"},
101 {AudioChannelLayout::HEXADECAGONAL, "HEXADECAGONAL"},
102 {AudioChannelLayout::STEREO_DOWNMIX, "STEREO_DOWNMIX"},
103 {AudioChannelLayout::HOA_FIRST, "HOA_FIRST"},
104 {AudioChannelLayout::HOA_SECOND, "HOA_SECOND"},
105 {AudioChannelLayout::HOA_THIRD, "HOA_THIRD"},
106 };
107
ConvertFFMpegAVCodecIdToOHAudioFormat(AVCodecID codecId)108 AudioSampleFormat FFMpegConverter::ConvertFFMpegAVCodecIdToOHAudioFormat(AVCodecID codecId)
109 {
110 auto ite = std::find_if(g_pFfCodeIDToSampleFmtMap.begin(), g_pFfCodeIDToSampleFmtMap.end(),
111 [&codecId](const auto &item) -> bool { return item.first == codecId; });
112 if (ite == g_pFfCodeIDToSampleFmtMap.end()) {
113 return AudioSampleFormat::INVALID_WIDTH;
114 }
115 return ite->second;
116 }
117
ConvertFFMpegToOHAudioFormat(AVSampleFormat ffSampleFormat)118 AudioSampleFormat FFMpegConverter::ConvertFFMpegToOHAudioFormat(AVSampleFormat ffSampleFormat)
119 {
120 auto ite = std::find_if(g_pFfSampleFmtMap.begin(), g_pFfSampleFmtMap.end(),
121 [&ffSampleFormat](const auto &item) -> bool { return item.first == ffSampleFormat; });
122 if (ite == g_pFfSampleFmtMap.end()) {
123 return AudioSampleFormat::INVALID_WIDTH;
124 }
125 return ite->second;
126 }
127
ConvertOHAudioFormatToFFMpeg(AudioSampleFormat sampleFormat)128 AVSampleFormat FFMpegConverter::ConvertOHAudioFormatToFFMpeg(AudioSampleFormat sampleFormat)
129 {
130 auto ite = std::find_if(g_pFfSampleFmtMap.begin(), g_pFfSampleFmtMap.end(),
131 [&sampleFormat](const auto &item) -> bool { return item.second == sampleFormat; });
132 if (ite == g_pFfSampleFmtMap.end()) {
133 return AVSampleFormat::AV_SAMPLE_FMT_NONE;
134 }
135 return ite->first;
136 }
137
ConvertFFToOHAudioChannelLayout(uint64_t ffChannelLayout)138 AudioChannelLayout FFMpegConverter::ConvertFFToOHAudioChannelLayout(uint64_t ffChannelLayout)
139 {
140 auto ite = std::find_if(g_toFFMPEGChannelLayout.begin(), g_toFFMPEGChannelLayout.end(),
141 [&ffChannelLayout](const auto &item) -> bool { return item.second == ffChannelLayout; });
142 if (ite == g_toFFMPEGChannelLayout.end()) {
143 return AudioChannelLayout::MONO;
144 }
145 return ite->first;
146 }
147
ConvertOHAudioChannelLayoutToFFMpeg(AudioChannelLayout channelLayout)148 uint64_t FFMpegConverter::ConvertOHAudioChannelLayoutToFFMpeg(AudioChannelLayout channelLayout)
149 {
150 auto ite = std::find_if(g_toFFMPEGChannelLayout.begin(), g_toFFMPEGChannelLayout.end(),
151 [&channelLayout](const auto &item) -> bool { return item.first == channelLayout; });
152 if (ite == g_toFFMPEGChannelLayout.end()) {
153 return AV_CH_LAYOUT_NATIVE;
154 }
155 return ite->second;
156 }
157
ConvertOHAudioChannelLayoutToString(AudioChannelLayout layout)158 std::string_view FFMpegConverter::ConvertOHAudioChannelLayoutToString(AudioChannelLayout layout)
159 {
160 auto ite = std::find_if(g_ChannelLayoutToString.begin(), g_ChannelLayoutToString.end(),
161 [&layout](const auto &item) -> bool { return item.first == layout; });
162 if (ite == g_ChannelLayoutToString.end()) {
163 return g_ChannelLayoutToString[0].second;
164 }
165 return ite->second;
166 }
167
ConvertAudioPtsToUs(int64_t pts,AVRational base)168 int64_t FFMpegConverter::ConvertAudioPtsToUs(int64_t pts, AVRational base)
169 {
170 if (pts == AV_NOPTS_VALUE) {
171 return -1;
172 }
173 AVRational us = {1, US_PER_SECOND};
174 return av_rescale_q(pts, base, us);
175 }
176
AVStrError(int errnum)177 std::string FFMpegConverter::AVStrError(int errnum)
178 {
179 char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
180 av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
181 return std::string(errbuf);
182 }
183 } // namespace MediaAVCodec
184 } // namespace OHOS