• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 <chrono>
17 #include <cstdio>
18 #include <thread>
19 #include <climits>
20 #include <cstdlib>
21 #include "audio_log.h"
22 #include "audio_renderer.h"
23 #include "pcm2wav.h"
24 
25 using namespace std;
26 using namespace OHOS;
27 using namespace OHOS::AudioStandard;
28 
29 namespace {
30     constexpr int32_t SAMPLE_FORMAT_U8 = 8;
31     constexpr int32_t SAMPLE_FORMAT_S16LE = 16;
32     constexpr int32_t SAMPLE_FORMAT_S24LE = 24;
33     constexpr int32_t SAMPLE_FORMAT_S32LE = 32;
34 }
35 class AudioRenderModeCallbackTest : public AudioRendererWriteCallback,
36     public enable_shared_from_this<AudioRenderModeCallbackTest> {
37 public:
OnWriteData(size_t length)38     void OnWriteData(size_t length) override
39     {
40         AUDIO_INFO_LOG("RenderCallbackTest: OnWriteData is called");
41         reqBufLen_ = length;
42         isEnqueue_ = true;
43     }
44 
GetSampleFormat(int32_t wavSampleFormat)45     AudioSampleFormat GetSampleFormat(int32_t wavSampleFormat)
46     {
47         switch (wavSampleFormat) {
48             case SAMPLE_FORMAT_U8:
49                 return AudioSampleFormat::SAMPLE_U8;
50             case SAMPLE_FORMAT_S16LE:
51                 return AudioSampleFormat::SAMPLE_S16LE;
52             case SAMPLE_FORMAT_S24LE:
53                 return AudioSampleFormat::SAMPLE_S24LE;
54             case SAMPLE_FORMAT_S32LE:
55                 return AudioSampleFormat::SAMPLE_S32LE;
56             default:
57                 return AudioSampleFormat::INVALID_WIDTH;
58         }
59     }
60 
InitRender()61     bool InitRender()
62     {
63         wav_hdr wavHeader;
64         size_t headerSize = sizeof(wav_hdr);
65         size_t bytesRead = fread(&wavHeader, 1, headerSize, wavFile_);
66         if (bytesRead != headerSize) {
67             AUDIO_ERR_LOG("RenderCallbackTest: File header reading error");
68             return false;
69         }
70 
71         AudioRendererOptions rendererOptions = {};
72         rendererOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
73         rendererOptions.streamInfo.samplingRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
74         rendererOptions.streamInfo.format = GetSampleFormat(wavHeader.bitsPerSample);
75         rendererOptions.streamInfo.channels = static_cast<AudioChannel>(wavHeader.NumOfChan);
76         rendererOptions.rendererInfo.contentType = ContentType::CONTENT_TYPE_MUSIC;
77         rendererOptions.rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
78         rendererOptions.rendererInfo.rendererFlags = 0;
79 
80         audioRenderer_ = AudioRenderer::Create(rendererOptions);
81         if (audioRenderer_== nullptr) {
82             AUDIO_ERR_LOG("RenderCallbackTest: Renderer create failed");
83             return false;
84         }
85 
86         AUDIO_INFO_LOG("RenderCallbackTest: Playback renderer created");
87         if (audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK)) {
88             AUDIO_ERR_LOG("RenderCallbackTest: SetRenderMode failed");
89             return false;
90         }
91 
92         if (audioRenderer_->SetRendererWriteCallback(shared_from_this())) {
93             AUDIO_ERR_LOG("RenderCallbackTest: SetRendererWriteCallback failed");
94             return false;
95         }
96 
97         audioRenderer_->GetBufferSize(reqBufLen_);
98 
99         return true;
100     }
101 
TestPlayback(int argc,char * argv[])102     int32_t TestPlayback(int argc, char *argv[])
103     {
104         AUDIO_INFO_LOG("RenderCallbackTest: TestPlayback start");
105         if (!InitRender()) {
106             return -1;
107         }
108 
109         if (!audioRenderer_->Start()) {
110             AUDIO_ERR_LOG("RenderCallbackTest: Start failed");
111             audioRenderer_->Release();
112             return -1;
113         }
114 
115         enqueueThread_ = make_unique<thread>(&AudioRenderModeCallbackTest::EnqueueBuffer, this);
116         enqueueThread_ ->join();
117 
118         audioRenderer_->Clear();
119         audioRenderer_->Stop();
120         audioRenderer_->Release();
121         AUDIO_INFO_LOG("RenderCallbackTest: TestPlayback end");
122 
123         return 0;
124     }
125 
~AudioRenderModeCallbackTest()126     ~AudioRenderModeCallbackTest()
127     {
128         AUDIO_INFO_LOG("RenderCallbackTest: Inside ~AudioRenderModeCallbackTest");
129         if (fclose(wavFile_)) {
130             AUDIO_INFO_LOG("RenderCallbackTest: wavFile_ failed");
131         } else {
132             AUDIO_INFO_LOG("RenderCallbackTest: fclose(wavFile_) success");
133         }
134         wavFile_ = nullptr;
135 
136         if (enqueueThread_ && enqueueThread_->joinable()) {
137             enqueueThread_->join();
138             enqueueThread_ = nullptr;
139         }
140     }
141 
142     FILE *wavFile_ = nullptr;
143 private:
EnqueueBuffer()144     void EnqueueBuffer()
145     {
146         AUDIO_INFO_LOG("RenderCallbackTest: EnqueueBuffer thread");
147         while (!feof(wavFile_)) {
148             if (isEnqueue_) {
149                 // Requested length received in callback
150                 size_t reqLen = reqBufLen_;
151                 bufDesc_.buffer = nullptr;
152                 audioRenderer_->GetBufferDesc(bufDesc_);
153                 if (bufDesc_.buffer == nullptr) {
154                     continue;
155                 }
156                 // requested len in callback will never be greater than allocated buf length
157                 // This is just a fail-safe
158                 if (reqLen > bufDesc_.bufLength) {
159                     bufDesc_.dataLength = bufDesc_.bufLength;
160                 } else {
161                     bufDesc_.dataLength = reqLen;
162                 }
163 
164                 fread(bufDesc_.buffer, 1, bufDesc_.dataLength, wavFile_);
165                 audioRenderer_->Enqueue(bufDesc_);
166                 isEnqueue_ = false;
167             }
168         }
169     }
170 
171     unique_ptr<AudioRenderer> audioRenderer_ = nullptr;
172     unique_ptr<thread> enqueueThread_ = nullptr;
173     bool isEnqueue_ = true;
174     BufferDesc bufDesc_ {};
175     size_t reqBufLen_;
176 };
177 
main(int argc,char * argv[])178 int main(int argc, char *argv[])
179 {
180     char *inputPath = argv[1];
181     char path[PATH_MAX + 1] = {0x00};
182     if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
183         AUDIO_ERR_LOG("RenderCallbackTest: Invalid input filepath");
184         return -1;
185     }
186     AUDIO_INFO_LOG("RenderCallbackTest: path = %{public}s", path);
187     auto testObj = std::make_shared<AudioRenderModeCallbackTest>();
188 
189     testObj->wavFile_ = fopen(path, "rb");
190     if (testObj->wavFile_ == nullptr) {
191         AUDIO_ERR_LOG("AudioRendererTest: Unable to open wave file");
192         return -1;
193     }
194 
195     return testObj->TestPlayback(argc, argv);
196 }
197