• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 
16 #include "gtest/gtest.h"
17 #include "audio_ffmpeg_aac_encoder_plugin.h"
18 #include "audio_ffmpeg_flac_encoder_plugin.h"
19 #include <set>
20 #include <fstream>
21 #include "media_description.h"
22 #include "avcodec_errors.h"
23 #include "avcodec_trace.h"
24 #include "avcodec_log.h"
25 #include "avcodec_mime_type.h"
26 #include "avcodec_audio_common.h"
27 #include "ffmpeg_converter.h"
28 #include "audio_codec_adapter.h"
29 #include "meta/format.h"
30 #include "avcodec_audio_decoder.h"
31 #include "avcodec_codec_name.h"
32 
33 using namespace std;
34 using namespace OHOS::Media;
35 using namespace testing::ext;
36 
37 namespace {
38 constexpr int32_t MIN_CHANNELS = 2;
39 constexpr int32_t MAX_CHANNELS = 8;
40 constexpr int32_t AAC_SAMPLE_RATE = 44100;
41 constexpr int32_t AAC_BITRATE = 128000;
42 constexpr int32_t DEFAULT_AAC_TYPE = 1;
43 constexpr int32_t BUFFER_SIZE = 6400;
44 constexpr std::string_view AAC_NAME = "aac_enc_buffer";
45 constexpr std::string_view FLAC_NAME = "flac_enc_buffer";
46 constexpr uint32_t META_SIZE = 6400;
47 constexpr int32_t FLAC_CHANNELS = 2;
48 constexpr int32_t FLAC_ENC_SAMPLE_RATE = 32000;
49 constexpr int32_t FLAC_BITRATE = 32000;
50 constexpr int32_t ONE_FRAME_SIZE = 64000;
51 constexpr int32_t COMPLIANCE_LEVEL = 2;
52 }
53 
54 namespace OHOS {
55 namespace MediaAVCodec {
56 class AudioEncPluginUnitTest : public testing::Test {
57 public:
58     static void SetUpTestCase(void);
59     static void TearDownTestCase(void);
60     void SetUp();
61     void TearDown();
62     void PrepareFlacEncoder();
63     std::shared_ptr<AudioBufferInfo> CreateAudioBuffer(const std::vector<int16_t> &data, size_t offset,
64         size_t size, int64_t pts, bool isEos);
65     bool ProcessAudioData(const std::vector<int16_t> &pcmData, size_t offset, size_t size, int64_t pts);
66     bool FlushEncoder();
67 
68 protected:
69     OHOS::MediaAVCodec::Format aacFormat_;
70     OHOS::MediaAVCodec::Format flacFormat_;
71     std::shared_ptr<AudioFFMpegAacEncoderPlugin> aacEncPlugin_ = {nullptr};
72     std::shared_ptr<AudioFFMpegFlacEncoderPlugin> flacEncPlugin_ = {nullptr};
73 };
74 
SetUpTestCase(void)75 void AudioEncPluginUnitTest::SetUpTestCase(void)
76 {
77     cout << "[SetUpTestCase]: " << endl;
78 }
79 
TearDownTestCase(void)80 void AudioEncPluginUnitTest::TearDownTestCase(void)
81 {
82     cout << "[TearDownTestCase]: " << endl;
83 }
84 
SetUp(void)85 void AudioEncPluginUnitTest::SetUp(void)
86 {
87     aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, MAX_CHANNELS);
88     aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, AAC_SAMPLE_RATE);
89     aacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, AAC_BITRATE);
90     aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
91     aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AAC_IS_ADTS, DEFAULT_AAC_TYPE);
92 
93     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, FLAC_CHANNELS);
94     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
95     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, FLAC_ENC_SAMPLE_RATE);
96     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_BITRATE, FLAC_BITRATE);
97     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE, SAMPLE_S16LE);
98     flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_COMPLIANCE_LEVEL, COMPLIANCE_LEVEL);
99     flacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_CHANNEL_LAYOUT, AudioChannelLayout::STEREO);
100 
101     aacEncPlugin_ = std::make_shared<AudioFFMpegAacEncoderPlugin>();
102     flacEncPlugin_ = std::make_shared<AudioFFMpegFlacEncoderPlugin>();
103     cout << "[SetUp]: SetUp!!!" << endl;
104 }
105 
TearDown(void)106 void AudioEncPluginUnitTest::TearDown(void)
107 {
108     if (aacEncPlugin_) {
109         aacEncPlugin_->Release();
110     }
111     if (flacEncPlugin_) {
112         flacEncPlugin_->Release();
113     }
114     cout << "[TearDown]: over!!!" << endl;
115 }
116 
PrepareFlacEncoder()117 void AudioEncPluginUnitTest::PrepareFlacEncoder()
118 {
119     int32_t ret = flacEncPlugin_->Init(flacFormat_);
120     if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
121         cout << "Failed to initialize FLAC encoder" << endl;
122     }
123 }
124 
CreateAudioBuffer(const std::vector<int16_t> & data,size_t offset,size_t size,int64_t pts,bool isEos)125 std::shared_ptr<AudioBufferInfo> AudioEncPluginUnitTest::CreateAudioBuffer(const std::vector<int16_t> &data,
126     size_t offset, size_t size, int64_t pts, bool isEos)
127 {
128     auto buffer = std::make_shared<AudioBufferInfo>(size, FLAC_NAME, ONE_FRAME_SIZE);
129     auto memory = buffer->GetBuffer();
130     if (!memory) {
131         cout << "Failed to allocate memory for audio buffer" << endl;
132         return nullptr;
133     }
134 
135     if (size > 0) {
136         if (memcpy_s(memory->GetBase(), memory->GetSize(), data.data() + offset, size) != EOK) {
137             cout << "Fatal: memory copy failed (size=" << size
138                  << ", dest_size=" << memory->GetSize() << ")" << endl;
139         }
140     }
141 
142     AVCodecBufferInfo attr = {};
143     attr.size = size;
144     attr.presentationTimeUs = pts;
145     buffer->SetBufferAttr(attr);
146     buffer->SetEos(isEos);
147 
148     return buffer;
149 }
150 
ProcessAudioData(const std::vector<int16_t> & pcmData,size_t offset,size_t size,int64_t pts)151 bool AudioEncPluginUnitTest::ProcessAudioData(const std::vector<int16_t> &pcmData, size_t offset,
152     size_t size, int64_t pts)
153 {
154     auto inputBuffer = CreateAudioBuffer(pcmData, offset, size, pts, false);
155     if (!inputBuffer) {
156         return false;
157     }
158 
159     int32_t ret = flacEncPlugin_->ProcessSendData(inputBuffer);
160     while (true) {
161         auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
162         ret = flacEncPlugin_->ProcessRecieveData(outputBuffer);
163         if (ret == AVCodecServiceErrCode::AVCS_ERR_NOT_ENOUGH_DATA) {
164             break;
165         }
166         if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
167             cout <<"Failed to receive encoded data: " << ret << endl;
168             return false;
169         }
170     }
171     return true;
172 }
173 
FlushEncoder()174 bool AudioEncPluginUnitTest::FlushEncoder()
175 {
176     auto eosBuffer = CreateAudioBuffer({}, 0, 0, 0, true);
177     if (!eosBuffer) {
178         return false;
179     }
180 
181     int32_t ret = flacEncPlugin_->ProcessSendData(eosBuffer);
182     if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
183         cout << "Failed to send EOS: " << ret << endl;
184     }
185 
186     while (true) {
187         auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
188         ret = flacEncPlugin_->ProcessRecieveData(outputBuffer);
189         if (ret == AVCodecServiceErrCode::AVCS_ERR_END_OF_STREAM) {
190             break;
191         }
192         if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
193             cout << "Error during flush: " << ret << endl;
194             return false;
195         }
196     }
197     return true;
198 }
199 
200 
201 HWTEST_F(AudioEncPluginUnitTest, CheckBitRate_Aac_001, TestSize.Level1)
202 {
203     aacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, -44100); // invalid
204     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
205 }
206 
207 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_001, TestSize.Level1)
208 {
209     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
210     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
211     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
212     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
213 }
214 
215 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_002, TestSize.Level1)
216 {
217     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
218     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
219     inputBuffer->SetEos(false);
220     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
221 }
222 
223 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_003, TestSize.Level1)
224 {
225     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
226     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
227     inputBuffer->SetEos(false);
228 
229     AVCodecBufferInfo attr;
230     attr.size = -6400; // invalid
231     inputBuffer->SetBufferAttr(attr);
232     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
233 }
234 
235 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_004, TestSize.Level1)
236 {
237     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
238     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
239     inputBuffer->SetEos(false);
240 
241     AVCodecBufferInfo attr;
242     attr.size = 9600; // attr.size > 6400
243     inputBuffer->SetBufferAttr(attr);
244     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
245 }
246 
247 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_005, TestSize.Level1)
248 {
249     aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, MIN_CHANNELS);
250     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
251     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
252     inputBuffer->SetEos(false);
253 
254     AVCodecBufferInfo attr;
255     attr.size = 6400; // valid size
256     inputBuffer->SetBufferAttr(attr);
257     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
258 }
259 
260 HWTEST_F(AudioEncPluginUnitTest, ProcessRecieveData_Aac_001, TestSize.Level1)
261 {
262     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
263     auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
264     outputBuffer = nullptr;
265     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessRecieveData(outputBuffer));
266 }
267 
268 HWTEST_F(AudioEncPluginUnitTest, ProcessRecieveData_Aac_002, TestSize.Level1)
269 {
270     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
271     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
272     auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
273     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessRecieveData(outputBuffer));
274 }
275 
276 HWTEST_F(AudioEncPluginUnitTest, CheckResample_Aac_001, TestSize.Level1)
277 {
278     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
279     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
280     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
281 }
282 
283 HWTEST_F(AudioEncPluginUnitTest, ProcessSendData_Flac_001, TestSize.Level1)
284 {
285     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->Init(flacFormat_));
286     EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->Release());
287     auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
288 
289     EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->ProcessSendData(inputBuffer));
290 }
291 
292 HWTEST_F(AudioEncPluginUnitTest, FlacEncodeProcess_001, TestSize.Level1)
293 {
294     PrepareFlacEncoder();
295 
296     const int sampleRate = FLAC_ENC_SAMPLE_RATE;
297     const int durationSeconds = 5;
298     const int numSamples = sampleRate * durationSeconds;
299     const float amplitude = 32760.0f;
300 
301     std::vector<int16_t> pcmData(numSamples * FLAC_CHANNELS);
302     for (int i = 0; i < numSamples; ++i) {
303         for (int ch = 0; ch < FLAC_CHANNELS; ++ch) {
304             float frequency = 440.0f * (ch + 1);
305             float value = amplitude * sin(2.0f * M_PI * frequency * i / sampleRate);
306             pcmData[i * FLAC_CHANNELS + ch] = static_cast<int16_t>(value);
307         }
308     }
309 
310     int32_t frameSize = 1024;
311     const int bytesPerSample = 2;
312     const int bytesPerChunk = frameSize * FLAC_CHANNELS * bytesPerSample;
313     const int64_t timeIncrementUs = (frameSize * 1000000LL) / sampleRate;
314 
315     int64_t pts = 0;
316     for (size_t offset = 0; offset < pcmData.size() * bytesPerSample; offset += bytesPerChunk) {
317         size_t chunkSize = std::min(bytesPerChunk, static_cast<int>(pcmData.size() * bytesPerSample - offset));
318         if (chunkSize == 0) break;
319         if (!ProcessAudioData(pcmData, offset / bytesPerSample, chunkSize, pts)) {
320             break;
321         }
322         pts += timeIncrementUs;
323     }
324     EXPECT_EQ(FlushEncoder(), true);
325 }
326 } // namespace MediaAVCodec
327 } // namespace OHOS