• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.codecId) ||
50         !audioPlayer_->SetAudioFormat(audioTrack.channels, audioTrack.sampleRate)) {
51         SHARING_LOGE("audio play init error.");
52         return false;
53     }
54 
55     return true;
56 }
57 
Start(BufferDispatcher::Ptr & dispatcher)58 bool AudioPlayController::Start(BufferDispatcher::Ptr &dispatcher)
59 {
60     SHARING_LOGD("trace.");
61     RETURN_FALSE_IF_NULL(dispatcher);
62     if (nullptr == audioPlayer_) {
63         SHARING_LOGE("audio play need init first.");
64         return false;
65     }
66 
67     if (isAudioRunning_) {
68         SHARING_LOGW("audio play is running.");
69         return true;
70     }
71 
72     if (audioPlayer_->Start()) {
73         isAudioRunning_ = true;
74         dispatcher->AttachReceiver(bufferReceiver_);
75         StartAudioThread();
76     } else {
77         return false;
78     }
79 
80     return true;
81 }
82 
Stop(BufferDispatcher::Ptr & dispatcher)83 void AudioPlayController::Stop(BufferDispatcher::Ptr &dispatcher)
84 {
85     SHARING_LOGD("trace.");
86     if (dispatcher && bufferReceiver_) {
87         dispatcher->DetachReceiver(bufferReceiver_);
88     }
89 
90     if (audioPlayer_) {
91         audioPlayer_->Stop();
92         isAudioRunning_ = false;
93         if (bufferReceiver_) {
94             bufferReceiver_->NotifyReadStop();
95         }
96         StopAudioThread();
97     }
98 }
99 
Release()100 void AudioPlayController::Release()
101 {
102     SHARING_LOGD("trace.");
103     if (nullptr != audioPlayer_) {
104         audioPlayer_->Release();
105         audioPlayer_.reset();
106     }
107 }
108 
StartAudioThread()109 void AudioPlayController::StartAudioThread()
110 {
111     SHARING_LOGD("trace.");
112     if (audioPlayThread_ != nullptr) {
113         SHARING_LOGD("thread already exist, mediachannelId: %{public}u.", mediachannelId_);
114         return;
115     }
116 
117     audioPlayThread_ = std::make_shared<std::thread>(&AudioPlayController::AudioPlayThread, this);
118     std::string name = "audioplay";
119     pthread_setname_np(audioPlayThread_->native_handle(), name.c_str());
120     if (audioPlayThread_ == nullptr) {
121         SHARING_LOGE("play start create thread error, mediachannelId: %{public}u!", mediachannelId_);
122     }
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