1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "audio_play_controller.h"
17 #include <chrono>
18 #include "common/common_macro.h"
19 #include "common/const_def.h"
20 #include "common/event_comm.h"
21 #include "common/media_log.h"
22 #include "magic_enum.hpp"
23 #include "utils/data_buffer.h"
24
25 namespace OHOS {
26 namespace Sharing {
27
AudioPlayController(uint32_t mediaChannelId)28 AudioPlayController::AudioPlayController(uint32_t mediaChannelId)
29 {
30 SHARING_LOGD("trace.");
31 bufferReceiver_ = std::make_shared<BufferReceiver>();
32 mediachannelId_ = mediaChannelId;
33 }
34
~AudioPlayController()35 AudioPlayController::~AudioPlayController()
36 {
37 SHARING_LOGD("delete audio play controller, mediachannelId: %{public}u.", mediachannelId_);
38 }
39
Init(AudioTrack & audioTrack)40 bool AudioPlayController::Init(AudioTrack &audioTrack)
41 {
42 SHARING_LOGD("trace.");
43 if (CODEC_NONE == audioTrack.codecId) {
44 SHARING_LOGW("no need to play.");
45 return false;
46 }
47
48 audioPlayer_ = std::make_shared<AudioPlayer>();
49 if (!audioPlayer_->Init(audioTrack)) {
50 SHARING_LOGE("audio play init error.");
51 return false;
52 }
53
54 return true;
55 }
56
Start(BufferDispatcher::Ptr & dispatcher)57 bool AudioPlayController::Start(BufferDispatcher::Ptr &dispatcher)
58 {
59 SHARING_LOGD("trace.");
60 RETURN_FALSE_IF_NULL(dispatcher);
61 if (nullptr == audioPlayer_) {
62 SHARING_LOGE("audio play need init first.");
63 return false;
64 }
65
66 if (isAudioRunning_) {
67 SHARING_LOGW("audio play is running.");
68 return true;
69 }
70
71 if (audioPlayer_->Start()) {
72 isAudioRunning_ = true;
73 dispatcher->AttachReceiver(bufferReceiver_);
74 StartAudioThread();
75 } else {
76 return false;
77 }
78
79 return true;
80 }
81
Stop(BufferDispatcher::Ptr & dispatcher)82 void AudioPlayController::Stop(BufferDispatcher::Ptr &dispatcher)
83 {
84 SHARING_LOGD("trace.");
85 if (dispatcher && bufferReceiver_) {
86 dispatcher->DetachReceiver(bufferReceiver_);
87 }
88
89 if (audioPlayer_) {
90 audioPlayer_->Stop();
91 isAudioRunning_ = false;
92 if (bufferReceiver_) {
93 bufferReceiver_->NotifyReadStop();
94 }
95 StopAudioThread();
96 }
97 }
98
Release()99 void AudioPlayController::Release()
100 {
101 SHARING_LOGD("trace.");
102 if (nullptr != audioPlayer_) {
103 audioPlayer_->Release();
104 audioPlayer_.reset();
105 }
106 }
107
StartAudioThread()108 void AudioPlayController::StartAudioThread()
109 {
110 SHARING_LOGD("trace.");
111 if (audioPlayThread_ != nullptr) {
112 SHARING_LOGD("thread already exist, mediachannelId: %{public}u.", mediachannelId_);
113 return;
114 }
115
116 audioPlayThread_ = std::make_shared<std::thread>(&AudioPlayController::AudioPlayThread, this);
117 if (audioPlayThread_ == nullptr) {
118 SHARING_LOGE("play start create thread error, mediachannelId: %{public}u!", mediachannelId_);
119 return;
120 }
121 std::string name = "audioplay";
122 pthread_setname_np(audioPlayThread_->native_handle(), name.c_str());
123 }
124
StopAudioThread()125 void AudioPlayController::StopAudioThread()
126 {
127 SHARING_LOGD("trace.");
128 if (audioPlayThread_) {
129 if (audioPlayThread_->joinable()) {
130 audioPlayThread_->join();
131 }
132 audioPlayThread_ = nullptr;
133 }
134
135 SHARING_LOGD("stop audio thread exit, mediachannelId: %{public}u.", mediachannelId_);
136 }
137
AudioPlayThread()138 void AudioPlayController::AudioPlayThread()
139 {
140 SHARING_LOGD("audio play thread start mediachannelId: %{public}u ,tid: %{public}d.", mediachannelId_, gettid());
141 while (isAudioRunning_) {
142 MEDIA_LOGD("try read audio data mediaChannelId: %{public}u.", mediachannelId_);
143 MediaData::Ptr outData = std::make_shared<MediaData>();
144 outData->buff = std::make_shared<DataBuffer>();
145 int32_t ret = 0;
146 if (bufferReceiver_) {
147 ret = bufferReceiver_->RequestRead(MediaType::MEDIA_TYPE_AUDIO, [&outData](const MediaData::Ptr &data) {
148 MEDIA_LOGD("request start.");
149 if (data == nullptr) {
150 return;
151 }
152 outData->buff->ReplaceData(data->buff->Peek(), data->buff->Size());
153 outData->keyFrame = data->keyFrame;
154 outData->mediaType = data->mediaType;
155 outData->pts = data->pts;
156 outData->isRaw = data->isRaw;
157 outData->ssrc = data->ssrc;
158 MEDIA_LOGD("request end.");
159 });
160 }
161
162 if (ret != 0) {
163 MEDIA_LOGD("read data null mediaChannelId: %{public}u.", mediachannelId_);
164 continue;
165 }
166
167 if (audioPlayer_) {
168 MEDIA_LOGD("process audio mediaChannelId: %{public}u, size: %{public}d.", mediachannelId_,
169 outData->buff->Size());
170 audioPlayer_->ProcessAudioData(outData->buff);
171 }
172 }
173
174 SHARING_LOGD("audio play thread exit, mediachannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
175 }
176
SetVolume(float volume)177 void AudioPlayController::SetVolume(float volume)
178 {
179 SHARING_LOGD("Volume: %{public}f.", volume);
180 if (audioPlayer_) {
181 audioPlayer_->SetVolume(volume);
182 }
183 }
184
185 } // namespace Sharing
186 } // namespace OHOS