1e0e9324cSopenharmony_ci/*
2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License.
5e0e9324cSopenharmony_ci * You may obtain a copy of the License at
6e0e9324cSopenharmony_ci *
7e0e9324cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0e9324cSopenharmony_ci *
9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and
13e0e9324cSopenharmony_ci * limitations under the License.
14e0e9324cSopenharmony_ci */
15e0e9324cSopenharmony_ci
16e0e9324cSopenharmony_ci#include "buffer_dispatcher.h"
17e0e9324cSopenharmony_ci#include <cmath>
18e0e9324cSopenharmony_ci#include <cstdarg>
19e0e9324cSopenharmony_ci#include <cstdint>
20e0e9324cSopenharmony_ci#include "common/common_macro.h"
21e0e9324cSopenharmony_ci#include "media_channel_def.h"
22e0e9324cSopenharmony_ci
23e0e9324cSopenharmony_cinamespace OHOS {
24e0e9324cSopenharmony_cinamespace Sharing {
25e0e9324cSopenharmony_ci
26e0e9324cSopenharmony_ciconstexpr int32_t WRITING_TIMTOUT = 30;
27e0e9324cSopenharmony_ciconstexpr int32_t FIX_OFFSET_TWO = 2;
28e0e9324cSopenharmony_ciconstexpr int32_t FIX_OFFSET_ONE = 1;
29e0e9324cSopenharmony_ci
30e0e9324cSopenharmony_civoid BufferReceiver::SetSource(IBufferReader::Ptr dataReader)
31e0e9324cSopenharmony_ci{
32e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
33e0e9324cSopenharmony_ci    bufferReader_ = dataReader;
34e0e9324cSopenharmony_ci}
35e0e9324cSopenharmony_ci
36e0e9324cSopenharmony_ciint32_t BufferReceiver::OnMediaDataNotify()
37e0e9324cSopenharmony_ci{
38e0e9324cSopenharmony_ci    SHARING_LOGD("BufferReceiver Media notified.");
39e0e9324cSopenharmony_ci    dataReady_ = true;
40e0e9324cSopenharmony_ci    notifyData_.notify_one();
41e0e9324cSopenharmony_ci    return 0;
42e0e9324cSopenharmony_ci}
43e0e9324cSopenharmony_ci
44e0e9324cSopenharmony_ciint32_t BufferReceiver::OnAudioDataNotify()
45e0e9324cSopenharmony_ci{
46e0e9324cSopenharmony_ci    MEDIA_LOGD("BufferReceiver Audio notified.");
47e0e9324cSopenharmony_ci    nonBlockAudio_ = true;
48e0e9324cSopenharmony_ci    notifyAudio_.notify_one();
49e0e9324cSopenharmony_ci    return 0;
50e0e9324cSopenharmony_ci}
51e0e9324cSopenharmony_ci
52e0e9324cSopenharmony_ciint32_t BufferReceiver::OnVideoDataNotify()
53e0e9324cSopenharmony_ci{
54e0e9324cSopenharmony_ci    MEDIA_LOGD("BufferReceiver Video notified.");
55e0e9324cSopenharmony_ci    nonBlockVideo_ = true;
56e0e9324cSopenharmony_ci    notifyVideo_.notify_one();
57e0e9324cSopenharmony_ci    return 0;
58e0e9324cSopenharmony_ci}
59e0e9324cSopenharmony_ci
60e0e9324cSopenharmony_cibool BufferReceiver::IsMixedReceiver()
61e0e9324cSopenharmony_ci{
62e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
63e0e9324cSopenharmony_ci    return mixed_;
64e0e9324cSopenharmony_ci}
65e0e9324cSopenharmony_ci
66e0e9324cSopenharmony_ciint32_t BufferReceiver::RequestRead(MediaType type, std::function<void(const MediaData::Ptr &data)> cb)
67e0e9324cSopenharmony_ci{
68e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
69e0e9324cSopenharmony_ci    if (bufferReader_ == nullptr) {
70e0e9324cSopenharmony_ci        SHARING_LOGE("BufferReceiver read failed null dispatcher.");
71e0e9324cSopenharmony_ci        return -1;
72e0e9324cSopenharmony_ci    }
73e0e9324cSopenharmony_ci
74e0e9324cSopenharmony_ci    if (firstMRead_ && type == MEDIA_TYPE_AV) {
75e0e9324cSopenharmony_ci        bufferReader_->NotifyReadReady(GetReceiverId(), type);
76e0e9324cSopenharmony_ci        mixed_ = true;
77e0e9324cSopenharmony_ci        firstMRead_ = false;
78e0e9324cSopenharmony_ci    } else if (firstARead_ && type == MEDIA_TYPE_AUDIO) {
79e0e9324cSopenharmony_ci        bufferReader_->NotifyReadReady(GetReceiverId(), type);
80e0e9324cSopenharmony_ci        firstARead_ = false;
81e0e9324cSopenharmony_ci    } else if (firstVRead_ && type == MEDIA_TYPE_VIDEO) {
82e0e9324cSopenharmony_ci        bufferReader_->NotifyReadReady(GetReceiverId(), type);
83e0e9324cSopenharmony_ci        firstVRead_ = false;
84e0e9324cSopenharmony_ci    }
85e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> locker(mutex_);
86e0e9324cSopenharmony_ci    MEDIA_LOGD("BufferDispatcher NotifyThreadWorker before wait, receiverId: %{public}u.", GetReceiverId());
87e0e9324cSopenharmony_ci    switch (type) {
88e0e9324cSopenharmony_ci        /*  cv will waiting if pred is false;
89e0e9324cSopenharmony_ci            so set waiting audio pred (type != MEDIA_TYPE_AUDIO) to NOT block other type.*/
90e0e9324cSopenharmony_ci        case MEDIA_TYPE_AUDIO:
91e0e9324cSopenharmony_ci            MEDIA_LOGD("wait Audio, receiverId: %{public}u.", GetReceiverId());
92e0e9324cSopenharmony_ci            notifyAudio_.wait(locker, [=]() { return nonBlockAudio_ || type != MEDIA_TYPE_AUDIO; });
93e0e9324cSopenharmony_ci            nonBlockAudio_ = false;
94e0e9324cSopenharmony_ci            break;
95e0e9324cSopenharmony_ci        case MEDIA_TYPE_VIDEO:
96e0e9324cSopenharmony_ci            MEDIA_LOGD("wait Video, receiverId: %{public}u.", GetReceiverId());
97e0e9324cSopenharmony_ci            notifyVideo_.wait(locker, [=]() { return nonBlockVideo_ || type != MEDIA_TYPE_VIDEO; });
98e0e9324cSopenharmony_ci            nonBlockVideo_ = false;
99e0e9324cSopenharmony_ci            break;
100e0e9324cSopenharmony_ci        case MEDIA_TYPE_AV:
101e0e9324cSopenharmony_ci            MEDIA_LOGD("wait Mixed, receiverId: %{public}u.", GetReceiverId());
102e0e9324cSopenharmony_ci            notifyData_.wait(locker, [=]() { return dataReady_ || type != MEDIA_TYPE_AV; });
103e0e9324cSopenharmony_ci            dataReady_ = false;
104e0e9324cSopenharmony_ci            break;
105e0e9324cSopenharmony_ci        default:
106e0e9324cSopenharmony_ci            return 0;
107e0e9324cSopenharmony_ci            break;
108e0e9324cSopenharmony_ci    }
109e0e9324cSopenharmony_ci
110e0e9324cSopenharmony_ci    bufferReader_->ClearDataBit(GetReceiverId(), type);
111e0e9324cSopenharmony_ci    bufferReader_->ClearReadBit(GetReceiverId(), type);
112e0e9324cSopenharmony_ci    MEDIA_LOGD("BufferDispatcher NotifyThreadWorker after wait  start read, receiverId: %{public}u.", GetReceiverId());
113e0e9324cSopenharmony_ci    int32_t ret = bufferReader_->ReadBufferData(GetReceiverId(), type, cb);
114e0e9324cSopenharmony_ci    bufferReader_->NotifyReadReady(GetReceiverId(), type);
115e0e9324cSopenharmony_ci    dataReady_ = false;
116e0e9324cSopenharmony_ci
117e0e9324cSopenharmony_ci    return ret;
118e0e9324cSopenharmony_ci}
119e0e9324cSopenharmony_ci
120e0e9324cSopenharmony_civoid BufferReceiver::NotifyReadStart()
121e0e9324cSopenharmony_ci{
122e0e9324cSopenharmony_ci    SHARING_LOGD("receiverId: %{public}u notify start read.", GetReceiverId());
123e0e9324cSopenharmony_ci    firstARead_ = true;
124e0e9324cSopenharmony_ci    firstVRead_ = true;
125e0e9324cSopenharmony_ci    firstMRead_ = true;
126e0e9324cSopenharmony_ci}
127e0e9324cSopenharmony_ci
128e0e9324cSopenharmony_ciuint32_t BufferReceiver::GetReceiverId()
129e0e9324cSopenharmony_ci{
130e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
131e0e9324cSopenharmony_ci    return GetId();
132e0e9324cSopenharmony_ci}
133e0e9324cSopenharmony_ci
134e0e9324cSopenharmony_ciuint32_t BufferReceiver::GetDispatcherId()
135e0e9324cSopenharmony_ci{
136e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
137e0e9324cSopenharmony_ci    if (bufferReader_) {
138e0e9324cSopenharmony_ci        return bufferReader_->GetDispatcherId();
139e0e9324cSopenharmony_ci    }
140e0e9324cSopenharmony_ci
141e0e9324cSopenharmony_ci    return 0;
142e0e9324cSopenharmony_ci}
143e0e9324cSopenharmony_ci
144e0e9324cSopenharmony_civoid BufferReceiver::NotifyReadStop()
145e0e9324cSopenharmony_ci{
146e0e9324cSopenharmony_ci    SHARING_LOGD("receiverId: %{public}u notify stop read.", GetReceiverId());
147e0e9324cSopenharmony_ci    nonBlockAudio_ = true;
148e0e9324cSopenharmony_ci    nonBlockVideo_ = true;
149e0e9324cSopenharmony_ci    dataReady_ = true;
150e0e9324cSopenharmony_ci    notifyAudio_.notify_all();
151e0e9324cSopenharmony_ci    notifyVideo_.notify_all();
152e0e9324cSopenharmony_ci    notifyData_.notify_all();
153e0e9324cSopenharmony_ci}
154e0e9324cSopenharmony_ci
155e0e9324cSopenharmony_civoid BufferReceiver::EnableKeyMode(bool enable)
156e0e9324cSopenharmony_ci{
157e0e9324cSopenharmony_ci    SHARING_LOGD("bufferReceiver id %{public}u SetKeyOnlyMode %{public}d.", GetReceiverId(), enable);
158e0e9324cSopenharmony_ci    if (keyOnly_ == true && enable == false) {
159e0e9324cSopenharmony_ci        SHARING_LOGD("Set KeyOnlyMode false, need report fast read over.");
160e0e9324cSopenharmony_ci        accelerationDone_ = true;
161e0e9324cSopenharmony_ci    }
162e0e9324cSopenharmony_ci
163e0e9324cSopenharmony_ci    keyOnly_ = enable;
164e0e9324cSopenharmony_ci    if (bufferReader_ && enable) {
165e0e9324cSopenharmony_ci        bufferReader_->ClearDataBit(GetReceiverId(), MEDIA_TYPE_VIDEO);
166e0e9324cSopenharmony_ci    }
167e0e9324cSopenharmony_ci
168e0e9324cSopenharmony_ci    auto listener = listener_.lock();
169e0e9324cSopenharmony_ci    if (listener) {
170e0e9324cSopenharmony_ci        listener->OnKeyModeNotify(enable);
171e0e9324cSopenharmony_ci    }
172e0e9324cSopenharmony_ci}
173e0e9324cSopenharmony_ci
174e0e9324cSopenharmony_cibool BufferReceiver::IsKeyMode()
175e0e9324cSopenharmony_ci{
176e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
177e0e9324cSopenharmony_ci    return keyOnly_;
178e0e9324cSopenharmony_ci}
179e0e9324cSopenharmony_ci
180e0e9324cSopenharmony_cibool BufferReceiver::IsKeyRedirect()
181e0e9324cSopenharmony_ci{
182e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
183e0e9324cSopenharmony_ci    return keyRedirect_;
184e0e9324cSopenharmony_ci}
185e0e9324cSopenharmony_ci
186e0e9324cSopenharmony_ciconst MediaData::Ptr BufferReceiver::GetSPS()
187e0e9324cSopenharmony_ci{
188e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
189e0e9324cSopenharmony_ci    if (bufferReader_) {
190e0e9324cSopenharmony_ci        return bufferReader_->GetSPS();
191e0e9324cSopenharmony_ci    }
192e0e9324cSopenharmony_ci
193e0e9324cSopenharmony_ci    return nullptr;
194e0e9324cSopenharmony_ci}
195e0e9324cSopenharmony_ci
196e0e9324cSopenharmony_ciconst MediaData::Ptr BufferReceiver::GetPPS()
197e0e9324cSopenharmony_ci{
198e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
199e0e9324cSopenharmony_ci    if (bufferReader_) {
200e0e9324cSopenharmony_ci        return bufferReader_->GetPPS();
201e0e9324cSopenharmony_ci    }
202e0e9324cSopenharmony_ci
203e0e9324cSopenharmony_ci    return nullptr;
204e0e9324cSopenharmony_ci}
205e0e9324cSopenharmony_ci
206e0e9324cSopenharmony_cibool BufferReceiver::NeedAcceleration()
207e0e9324cSopenharmony_ci{
208e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
209e0e9324cSopenharmony_ci    return accelerationDone_;
210e0e9324cSopenharmony_ci}
211e0e9324cSopenharmony_ci
212e0e9324cSopenharmony_civoid BufferReceiver::DisableAcceleration()
213e0e9324cSopenharmony_ci{
214e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
215e0e9324cSopenharmony_ci    accelerationDone_ = false;
216e0e9324cSopenharmony_ci}
217e0e9324cSopenharmony_ci
218e0e9324cSopenharmony_civoid BufferReceiver::SendAccelerationDone()
219e0e9324cSopenharmony_ci{
220e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
221e0e9324cSopenharmony_ci    auto listener = listener_.lock();
222e0e9324cSopenharmony_ci    if (listener) {
223e0e9324cSopenharmony_ci        listener->OnAccelerationDoneNotify();
224e0e9324cSopenharmony_ci    }
225e0e9324cSopenharmony_ci}
226e0e9324cSopenharmony_ci
227e0e9324cSopenharmony_civoid BufferReceiver::EnableKeyRedirect(bool enable)
228e0e9324cSopenharmony_ci{
229e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
230e0e9324cSopenharmony_ci    if (bufferReader_ && enable) {
231e0e9324cSopenharmony_ci        bufferReader_->EnableKeyRedirect(enable);
232e0e9324cSopenharmony_ci    }
233e0e9324cSopenharmony_ci    keyRedirect_ = enable;
234e0e9324cSopenharmony_ci}
235e0e9324cSopenharmony_ci
236e0e9324cSopenharmony_civoid BufferReceiver::SetBufferReceiverListener(std::weak_ptr<IBufferReceiverListener> listener)
237e0e9324cSopenharmony_ci{
238e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
239e0e9324cSopenharmony_ci    listener_ = listener;
240e0e9324cSopenharmony_ci}
241e0e9324cSopenharmony_ci
242e0e9324cSopenharmony_ciusing DataNotifier = BufferDispatcher::DataNotifier;
243e0e9324cSopenharmony_ci
244e0e9324cSopenharmony_civoid DataNotifier::NotifyDataReceiver(MediaType type)
245e0e9324cSopenharmony_ci{
246e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
247e0e9324cSopenharmony_ci    if (receiver_.lock() == nullptr) {
248e0e9324cSopenharmony_ci        SHARING_LOGE("target receiver NOT exist.");
249e0e9324cSopenharmony_ci        return;
250e0e9324cSopenharmony_ci    }
251e0e9324cSopenharmony_ci
252e0e9324cSopenharmony_ci    if (block_) {
253e0e9324cSopenharmony_ci        return;
254e0e9324cSopenharmony_ci    }
255e0e9324cSopenharmony_ci
256e0e9324cSopenharmony_ci    MEDIA_LOGD("notify target type %{public}d.", type);
257e0e9324cSopenharmony_ci    switch (type) {
258e0e9324cSopenharmony_ci        case MEDIA_TYPE_AUDIO:
259e0e9324cSopenharmony_ci            GetBufferReceiver()->OnAudioDataNotify();
260e0e9324cSopenharmony_ci            break;
261e0e9324cSopenharmony_ci        case MEDIA_TYPE_VIDEO:
262e0e9324cSopenharmony_ci            GetBufferReceiver()->OnVideoDataNotify();
263e0e9324cSopenharmony_ci            break;
264e0e9324cSopenharmony_ci        case MEDIA_TYPE_AV:
265e0e9324cSopenharmony_ci            GetBufferReceiver()->OnMediaDataNotify();
266e0e9324cSopenharmony_ci            break;
267e0e9324cSopenharmony_ci        default:
268e0e9324cSopenharmony_ci            SHARING_LOGI("none process case.");
269e0e9324cSopenharmony_ci            break;
270e0e9324cSopenharmony_ci    }
271e0e9324cSopenharmony_ci}
272e0e9324cSopenharmony_ci
273e0e9324cSopenharmony_ciBufferReceiver::Ptr DataNotifier::GetBufferReceiver()
274e0e9324cSopenharmony_ci{
275e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
276e0e9324cSopenharmony_ci    return receiver_.lock();
277e0e9324cSopenharmony_ci}
278e0e9324cSopenharmony_ci
279e0e9324cSopenharmony_ciuint32_t DataNotifier::GetReceiverId()
280e0e9324cSopenharmony_ci{
281e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
282e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
283e0e9324cSopenharmony_ci    if (receiver == nullptr) {
284e0e9324cSopenharmony_ci        SHARING_LOGE("target receiver NOT exist.");
285e0e9324cSopenharmony_ci        return INVALID_INDEX;
286e0e9324cSopenharmony_ci    }
287e0e9324cSopenharmony_ci
288e0e9324cSopenharmony_ci    return receiver->GetReceiverId();
289e0e9324cSopenharmony_ci}
290e0e9324cSopenharmony_ci
291e0e9324cSopenharmony_civoid DataNotifier::SetListenDispatcher(IBufferReader::Ptr dispatcher)
292e0e9324cSopenharmony_ci{
293e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
294e0e9324cSopenharmony_ci    dispatcher_ = dispatcher;
295e0e9324cSopenharmony_ci}
296e0e9324cSopenharmony_ci
297e0e9324cSopenharmony_civoid DataNotifier::SetNotifyReceiver(BufferReceiver::Ptr receiver)
298e0e9324cSopenharmony_ci{
299e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
300e0e9324cSopenharmony_ci    receiver_ = receiver;
301e0e9324cSopenharmony_ci}
302e0e9324cSopenharmony_ci
303e0e9324cSopenharmony_civoid DataNotifier::SetBlock()
304e0e9324cSopenharmony_ci{
305e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
306e0e9324cSopenharmony_ci    block_ = true;
307e0e9324cSopenharmony_ci}
308e0e9324cSopenharmony_ci
309e0e9324cSopenharmony_civoid DataNotifier::SetNeedUpdate(bool enable, MediaType type)
310e0e9324cSopenharmony_ci{
311e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
312e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AUDIO) {
313e0e9324cSopenharmony_ci        needUpdateAIndex = enable;
314e0e9324cSopenharmony_ci    } else {
315e0e9324cSopenharmony_ci        needUpdateVIndex = enable;
316e0e9324cSopenharmony_ci    }
317e0e9324cSopenharmony_ci}
318e0e9324cSopenharmony_ci
319e0e9324cSopenharmony_cibool DataNotifier::DataAvailable(MediaType type)
320e0e9324cSopenharmony_ci{
321e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
322e0e9324cSopenharmony_ci    auto dispatcher = dispatcher_.lock();
323e0e9324cSopenharmony_ci    if (dispatcher == nullptr) {
324e0e9324cSopenharmony_ci        SHARING_LOGE("target dispatcher NOT exist.");
325e0e9324cSopenharmony_ci        return false;
326e0e9324cSopenharmony_ci    }
327e0e9324cSopenharmony_ci
328e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AUDIO) {
329e0e9324cSopenharmony_ci        return audioIndex != INVALID_INDEX &&
330e0e9324cSopenharmony_ci               (audioIndex < dispatcher->GetLatestAudioIndex() || !dispatcher->IsRead(GetReceiverId(), audioIndex + 1));
331e0e9324cSopenharmony_ci    } else if (type == MEDIA_TYPE_VIDEO) {
332e0e9324cSopenharmony_ci        return videoIndex != INVALID_INDEX &&
333e0e9324cSopenharmony_ci               (videoIndex < dispatcher->GetLatestVideoIndex() || !dispatcher->IsRead(GetReceiverId(), videoIndex + 1));
334e0e9324cSopenharmony_ci    } else {
335e0e9324cSopenharmony_ci        return videoIndex != INVALID_INDEX &&
336e0e9324cSopenharmony_ci               (videoIndex < dispatcher->GetBufferSize() - 1 || !dispatcher->IsRead(GetReceiverId(), videoIndex + 1));
337e0e9324cSopenharmony_ci    }
338e0e9324cSopenharmony_ci
339e0e9324cSopenharmony_ci    return false;
340e0e9324cSopenharmony_ci}
341e0e9324cSopenharmony_ci
342e0e9324cSopenharmony_cibool DataNotifier::IsMixedReceiver()
343e0e9324cSopenharmony_ci{
344e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
345e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
346e0e9324cSopenharmony_ci    if (receiver == nullptr) {
347e0e9324cSopenharmony_ci        SHARING_LOGE("target receiver NOT exist.");
348e0e9324cSopenharmony_ci        return false;
349e0e9324cSopenharmony_ci    }
350e0e9324cSopenharmony_ci
351e0e9324cSopenharmony_ci    return receiver->IsMixedReceiver();
352e0e9324cSopenharmony_ci}
353e0e9324cSopenharmony_ci
354e0e9324cSopenharmony_ciuint32_t DataNotifier::GetReceiverReadIndex(MediaType type)
355e0e9324cSopenharmony_ci{
356e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
357e0e9324cSopenharmony_ci    switch (type) {
358e0e9324cSopenharmony_ci        case MEDIA_TYPE_VIDEO:
359e0e9324cSopenharmony_ci            MEDIA_LOGD("Video Recvid:%{public}d index: %{public}d.", GetReceiverId(), videoIndex);
360e0e9324cSopenharmony_ci            return videoIndex;
361e0e9324cSopenharmony_ci            break;
362e0e9324cSopenharmony_ci        case MEDIA_TYPE_AUDIO:
363e0e9324cSopenharmony_ci            MEDIA_LOGD("Audio Recvid:%{public}d index: %{public}d.", GetReceiverId(), audioIndex);
364e0e9324cSopenharmony_ci            return audioIndex;
365e0e9324cSopenharmony_ci            break;
366e0e9324cSopenharmony_ci        case MEDIA_TYPE_AV:
367e0e9324cSopenharmony_ci            MEDIA_LOGD("Mixed Recvid:%{public}d vindex: %{public}d  aindex: %{public}d.", GetReceiverId(), videoIndex,
368e0e9324cSopenharmony_ci                       audioIndex);
369e0e9324cSopenharmony_ci            if (audioIndex != INVALID_INDEX && videoIndex != INVALID_INDEX) {
370e0e9324cSopenharmony_ci                return audioIndex <= videoIndex ? audioIndex : videoIndex;
371e0e9324cSopenharmony_ci            } else if (audioIndex == INVALID_INDEX && videoIndex == INVALID_INDEX) {
372e0e9324cSopenharmony_ci                return INVALID_INDEX;
373e0e9324cSopenharmony_ci            } else {
374e0e9324cSopenharmony_ci                return audioIndex == INVALID_INDEX ? videoIndex : audioIndex;
375e0e9324cSopenharmony_ci            }
376e0e9324cSopenharmony_ci            break;
377e0e9324cSopenharmony_ci        default:
378e0e9324cSopenharmony_ci            return INVALID_INDEX;
379e0e9324cSopenharmony_ci            break;
380e0e9324cSopenharmony_ci    }
381e0e9324cSopenharmony_ci}
382e0e9324cSopenharmony_ci
383e0e9324cSopenharmony_cibool DataNotifier::IsKeyModeReceiver()
384e0e9324cSopenharmony_ci{
385e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
386e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
387e0e9324cSopenharmony_ci    if (receiver) {
388e0e9324cSopenharmony_ci        return receiver->IsKeyMode();
389e0e9324cSopenharmony_ci    }
390e0e9324cSopenharmony_ci
391e0e9324cSopenharmony_ci    return false;
392e0e9324cSopenharmony_ci}
393e0e9324cSopenharmony_ci
394e0e9324cSopenharmony_cibool DataNotifier::IsKeyRedirectReceiver()
395e0e9324cSopenharmony_ci{
396e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
397e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
398e0e9324cSopenharmony_ci    if (receiver) {
399e0e9324cSopenharmony_ci        return receiver->IsKeyRedirect();
400e0e9324cSopenharmony_ci    }
401e0e9324cSopenharmony_ci
402e0e9324cSopenharmony_ci    return false;
403e0e9324cSopenharmony_ci}
404e0e9324cSopenharmony_ci
405e0e9324cSopenharmony_cibool DataNotifier::NeedAcceleration()
406e0e9324cSopenharmony_ci{
407e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
408e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
409e0e9324cSopenharmony_ci    if (receiver == nullptr) {
410e0e9324cSopenharmony_ci        SHARING_LOGE("target receiver NOT exist.");
411e0e9324cSopenharmony_ci        return false;
412e0e9324cSopenharmony_ci    }
413e0e9324cSopenharmony_ci
414e0e9324cSopenharmony_ci    return receiver->NeedAcceleration();
415e0e9324cSopenharmony_ci}
416e0e9324cSopenharmony_ci
417e0e9324cSopenharmony_civoid DataNotifier::SendAccelerationDone()
418e0e9324cSopenharmony_ci{
419e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
420e0e9324cSopenharmony_ci    auto receiver = receiver_.lock();
421e0e9324cSopenharmony_ci    if (receiver == nullptr) {
422e0e9324cSopenharmony_ci        SHARING_LOGE("target receiver NOT exist.");
423e0e9324cSopenharmony_ci        return;
424e0e9324cSopenharmony_ci    }
425e0e9324cSopenharmony_ci
426e0e9324cSopenharmony_ci    receiver->SendAccelerationDone();
427e0e9324cSopenharmony_ci    receiver->DisableAcceleration();
428e0e9324cSopenharmony_ci}
429e0e9324cSopenharmony_ci
430e0e9324cSopenharmony_ciBufferDispatcher::BufferDispatcher(uint32_t maxCapacity, uint32_t capacityIncrement)
431e0e9324cSopenharmony_ci{
432e0e9324cSopenharmony_ci    SHARING_LOGD("BufferDispatcher ctor, set capacity: %{public}u.", maxCapacity);
433e0e9324cSopenharmony_ci    maxBufferCapacity_ = maxCapacity;
434e0e9324cSopenharmony_ci    bufferCapacityIncrement_ = capacityIncrement;
435e0e9324cSopenharmony_ci    {
436e0e9324cSopenharmony_ci        std::lock_guard<std::mutex> lock(idleMutex_);
437e0e9324cSopenharmony_ci        idleAudioBuffer_.set_capacity(INITIAL_BUFFER_CAPACITY);
438e0e9324cSopenharmony_ci        idleVideoBuffer_.set_capacity(INITIAL_BUFFER_CAPACITY);
439e0e9324cSopenharmony_ci        for (size_t i = 0; i < INITIAL_BUFFER_CAPACITY; i++) {
440e0e9324cSopenharmony_ci            MediaData::Ptr adata = std::make_shared<MediaData>();
441e0e9324cSopenharmony_ci            MediaData::Ptr vdata = std::make_shared<MediaData>();
442e0e9324cSopenharmony_ci            adata->buff = std::make_shared<DataBuffer>();
443e0e9324cSopenharmony_ci            vdata->buff = std::make_shared<DataBuffer>();
444e0e9324cSopenharmony_ci            idleAudioBuffer_.push_back(adata);
445e0e9324cSopenharmony_ci            idleVideoBuffer_.push_back(vdata);
446e0e9324cSopenharmony_ci        }
447e0e9324cSopenharmony_ci    }
448e0e9324cSopenharmony_ci
449e0e9324cSopenharmony_ci    writingTimer_ = std::make_unique<TimeoutTimer>("dispatcher-writing-timer");
450e0e9324cSopenharmony_ci
451e0e9324cSopenharmony_ci    std::unique_lock<std::shared_mutex> locker(bufferMutex_);
452e0e9324cSopenharmony_ci    circularBuffer_.set_capacity(INITIAL_BUFFER_CAPACITY);
453e0e9324cSopenharmony_ci    StartDispatch();
454e0e9324cSopenharmony_ci}
455e0e9324cSopenharmony_ci
456e0e9324cSopenharmony_ciBufferDispatcher::~BufferDispatcher()
457e0e9324cSopenharmony_ci{
458e0e9324cSopenharmony_ci    SHARING_LOGI("BufferDispatcher dtor.");
459e0e9324cSopenharmony_ci    running_ = false;
460e0e9324cSopenharmony_ci    StopDispatch();
461e0e9324cSopenharmony_ci    FlushBuffer();
462e0e9324cSopenharmony_ci    ReleaseIdleBuffer();
463e0e9324cSopenharmony_ci    ReleaseAllReceiver();
464e0e9324cSopenharmony_ci}
465e0e9324cSopenharmony_ci
466e0e9324cSopenharmony_civoid BufferDispatcher::StartDispatch()
467e0e9324cSopenharmony_ci{
468e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
469e0e9324cSopenharmony_ci    running_ = true;
470e0e9324cSopenharmony_ci    notifyThread_ = std::thread(&BufferDispatcher::NotifyThreadWorker, this);
471e0e9324cSopenharmony_ci    std::string name = "notifyThread";
472e0e9324cSopenharmony_ci    pthread_setname_np(notifyThread_.native_handle(), name.c_str());
473e0e9324cSopenharmony_ci}
474e0e9324cSopenharmony_ci
475e0e9324cSopenharmony_civoid BufferDispatcher::StopDispatch()
476e0e9324cSopenharmony_ci{
477e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
478e0e9324cSopenharmony_ci    running_ = false;
479e0e9324cSopenharmony_ci    continueNotify_ = true;
480e0e9324cSopenharmony_ci
481e0e9324cSopenharmony_ci    if (writingTimer_) {
482e0e9324cSopenharmony_ci        writingTimer_.reset();
483e0e9324cSopenharmony_ci    }
484e0e9324cSopenharmony_ci
485e0e9324cSopenharmony_ci    dataCV_.notify_all();
486e0e9324cSopenharmony_ci    if (notifyThread_.joinable()) {
487e0e9324cSopenharmony_ci        notifyThread_.join();
488e0e9324cSopenharmony_ci    }
489e0e9324cSopenharmony_ci}
490e0e9324cSopenharmony_ci
491e0e9324cSopenharmony_civoid BufferDispatcher::SetBufferCapacity(size_t capacity)
492e0e9324cSopenharmony_ci{
493e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
494e0e9324cSopenharmony_ci    std::unique_lock<std::shared_mutex> locker(bufferMutex_);
495e0e9324cSopenharmony_ci    circularBuffer_.set_capacity(capacity);
496e0e9324cSopenharmony_ci}
497e0e9324cSopenharmony_ci
498e0e9324cSopenharmony_civoid BufferDispatcher::SetDataMode(MediaDispacherMode dataMode)
499e0e9324cSopenharmony_ci{
500e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
501e0e9324cSopenharmony_ci    dataMode_ = dataMode;
502e0e9324cSopenharmony_ci}
503e0e9324cSopenharmony_ci
504e0e9324cSopenharmony_civoid BufferDispatcher::ReleaseIdleBuffer()
505e0e9324cSopenharmony_ci{
506e0e9324cSopenharmony_ci    SHARING_LOGD("BufferDispatcher idle Release Start.");
507e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> locker(idleMutex_);
508e0e9324cSopenharmony_ci    for (auto &data : idleAudioBuffer_) {
509e0e9324cSopenharmony_ci        if (data != nullptr && data->buff != nullptr) {
510e0e9324cSopenharmony_ci            data->buff.reset();
511e0e9324cSopenharmony_ci        }
512e0e9324cSopenharmony_ci    }
513e0e9324cSopenharmony_ci
514e0e9324cSopenharmony_ci    idleAudioBuffer_.clear();
515e0e9324cSopenharmony_ci    for (auto &data : idleVideoBuffer_) {
516e0e9324cSopenharmony_ci        if (data != nullptr && data->buff != nullptr) {
517e0e9324cSopenharmony_ci            data->buff.reset();
518e0e9324cSopenharmony_ci        }
519e0e9324cSopenharmony_ci    }
520e0e9324cSopenharmony_ci
521e0e9324cSopenharmony_ci    idleVideoBuffer_.clear();
522e0e9324cSopenharmony_ci    SHARING_LOGD("BufferDispatcher idle Release End.");
523e0e9324cSopenharmony_ci}
524e0e9324cSopenharmony_ci
525e0e9324cSopenharmony_civoid BufferDispatcher::FlushBuffer()
526e0e9324cSopenharmony_ci{
527e0e9324cSopenharmony_ci    SHARING_LOGI("BufferDispatcher Start flushing, dispatcherId: %{public}u.", GetDispatcherId());
528e0e9324cSopenharmony_ci    {
529e0e9324cSopenharmony_ci        std::lock_guard<std::mutex> lock(idleMutex_);
530e0e9324cSopenharmony_ci        idleAudioBuffer_.clear();
531e0e9324cSopenharmony_ci        idleVideoBuffer_.clear();
532e0e9324cSopenharmony_ci        for (size_t i = 0; i < INITIAL_BUFFER_CAPACITY; i++) {
533e0e9324cSopenharmony_ci            MediaData::Ptr adata = std::make_shared<MediaData>();
534e0e9324cSopenharmony_ci            MediaData::Ptr vdata = std::make_shared<MediaData>();
535e0e9324cSopenharmony_ci            adata->buff = std::make_shared<DataBuffer>();
536e0e9324cSopenharmony_ci            vdata->buff = std::make_shared<DataBuffer>();
537e0e9324cSopenharmony_ci            idleAudioBuffer_.push_back(adata);
538e0e9324cSopenharmony_ci            idleVideoBuffer_.push_back(vdata);
539e0e9324cSopenharmony_ci        }
540e0e9324cSopenharmony_ci    }
541e0e9324cSopenharmony_ci
542e0e9324cSopenharmony_ci    std::unique_lock<std::shared_mutex> locker(bufferMutex_);
543e0e9324cSopenharmony_ci    for (auto &data : circularBuffer_) {
544e0e9324cSopenharmony_ci        if (data->mediaData != nullptr && data->mediaData->buff != nullptr) {
545e0e9324cSopenharmony_ci            data->mediaData->buff.reset();
546e0e9324cSopenharmony_ci        }
547e0e9324cSopenharmony_ci    }
548e0e9324cSopenharmony_ci
549e0e9324cSopenharmony_ci    circularBuffer_.clear();
550e0e9324cSopenharmony_ci    waitingKey_ = true;
551e0e9324cSopenharmony_ci    gop_ = 0;
552e0e9324cSopenharmony_ci    audioFrameCnt_ = 0;
553e0e9324cSopenharmony_ci    videoFrameCnt_ = 0;
554e0e9324cSopenharmony_ci    ResetAllIndex();
555e0e9324cSopenharmony_ci    SHARING_LOGD("BufferDispatcher Dispatcher flushing end, dispatcherId: %{public}u.", GetDispatcherId());
556e0e9324cSopenharmony_ci}
557e0e9324cSopenharmony_ci
558e0e9324cSopenharmony_ciMediaData::Ptr BufferDispatcher::RequestDataBuffer(MediaType type, uint32_t size)
559e0e9324cSopenharmony_ci{
560e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
561e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(idleMutex_);
562e0e9324cSopenharmony_ci    if (size <= 0) {
563e0e9324cSopenharmony_ci        SHARING_LOGE("Size invalid.");
564e0e9324cSopenharmony_ci        return nullptr;
565e0e9324cSopenharmony_ci    }
566e0e9324cSopenharmony_ci
567e0e9324cSopenharmony_ci    MediaData::Ptr retData;
568e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_VIDEO) {
569e0e9324cSopenharmony_ci        if (!idleVideoBuffer_.empty()) {
570e0e9324cSopenharmony_ci            SHARING_LOGD("video From idle.");
571e0e9324cSopenharmony_ci            retData = idleVideoBuffer_.front();
572e0e9324cSopenharmony_ci            idleVideoBuffer_.pop_front();
573e0e9324cSopenharmony_ci            if (retData == nullptr) {
574e0e9324cSopenharmony_ci                MEDIA_LOGW("video From alloc when idle nullptr.");
575e0e9324cSopenharmony_ci                retData = std::make_shared<MediaData>();
576e0e9324cSopenharmony_ci            }
577e0e9324cSopenharmony_ci            return retData;
578e0e9324cSopenharmony_ci        }
579e0e9324cSopenharmony_ci    } else {
580e0e9324cSopenharmony_ci        if (!idleAudioBuffer_.empty()) {
581e0e9324cSopenharmony_ci            SHARING_LOGD("Audio From idle.");
582e0e9324cSopenharmony_ci            retData = idleAudioBuffer_.front();
583e0e9324cSopenharmony_ci            idleAudioBuffer_.pop_front();
584e0e9324cSopenharmony_ci            if (retData == nullptr) {
585e0e9324cSopenharmony_ci                MEDIA_LOGW("Audio From alloc when idle nullptr.");
586e0e9324cSopenharmony_ci                retData = std::make_shared<MediaData>();
587e0e9324cSopenharmony_ci            }
588e0e9324cSopenharmony_ci            return retData;
589e0e9324cSopenharmony_ci        }
590e0e9324cSopenharmony_ci    }
591e0e9324cSopenharmony_ci
592e0e9324cSopenharmony_ci    SHARING_LOGD("Audio/video from alloc.");
593e0e9324cSopenharmony_ci    retData = std::make_shared<MediaData>();
594e0e9324cSopenharmony_ci    return retData;
595e0e9324cSopenharmony_ci}
596e0e9324cSopenharmony_ci
597e0e9324cSopenharmony_civoid BufferDispatcher::ReturnIdleBuffer(DataSpec::Ptr &data)
598e0e9324cSopenharmony_ci{
599e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
600e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(idleMutex_);
601e0e9324cSopenharmony_ci    if (data == nullptr || data->mediaData == nullptr) {
602e0e9324cSopenharmony_ci        return;
603e0e9324cSopenharmony_ci    }
604e0e9324cSopenharmony_ci    if (data->mediaData->mediaType == MEDIA_TYPE_VIDEO) {
605e0e9324cSopenharmony_ci        if (idleVideoBuffer_.size() < INITIAL_BUFFER_CAPACITY) {
606e0e9324cSopenharmony_ci            idleVideoBuffer_.push_back(data->mediaData);
607e0e9324cSopenharmony_ci            MEDIA_LOGD("data: push_back in idleVideoBuffer_, size: %{public}zu.", idleVideoBuffer_.size());
608e0e9324cSopenharmony_ci        }
609e0e9324cSopenharmony_ci    } else {
610e0e9324cSopenharmony_ci        if (idleAudioBuffer_.size() < INITIAL_BUFFER_CAPACITY) {
611e0e9324cSopenharmony_ci            idleAudioBuffer_.push_back(data->mediaData);
612e0e9324cSopenharmony_ci            MEDIA_LOGD("data: push_back in idleAudioBuffer_, size: %{public}zu.", idleAudioBuffer_.size());
613e0e9324cSopenharmony_ci        }
614e0e9324cSopenharmony_ci    }
615e0e9324cSopenharmony_ci
616e0e9324cSopenharmony_ci    data.reset();
617e0e9324cSopenharmony_ci}
618e0e9324cSopenharmony_ci
619e0e9324cSopenharmony_cisize_t BufferDispatcher::GetBufferSize()
620e0e9324cSopenharmony_ci{
621e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
622e0e9324cSopenharmony_ci    return circularBuffer_.size();
623e0e9324cSopenharmony_ci}
624e0e9324cSopenharmony_ci
625e0e9324cSopenharmony_ciuint32_t BufferDispatcher::FindReceiverIndex(uint32_t receiverId)
626e0e9324cSopenharmony_ci{
627e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
628e0e9324cSopenharmony_ci    if (notifiers_.find(receiverId) != notifiers_.end()) {
629e0e9324cSopenharmony_ci        return notifiers_[receiverId]->GetReadIndex();
630e0e9324cSopenharmony_ci    }
631e0e9324cSopenharmony_ci
632e0e9324cSopenharmony_ci    return INVALID_INDEX;
633e0e9324cSopenharmony_ci}
634e0e9324cSopenharmony_ci
635e0e9324cSopenharmony_cibool BufferDispatcher::IsRecevierExist(uint32_t receiverId)
636e0e9324cSopenharmony_ci{
637e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
638e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverId(receiverId);
639e0e9324cSopenharmony_ci    if (notifier == nullptr) {
640e0e9324cSopenharmony_ci        return false;
641e0e9324cSopenharmony_ci    }
642e0e9324cSopenharmony_ci
643e0e9324cSopenharmony_ci    return true;
644e0e9324cSopenharmony_ci}
645e0e9324cSopenharmony_ci
646e0e9324cSopenharmony_civoid BufferDispatcher::EnableKeyMode(bool enable)
647e0e9324cSopenharmony_ci{
648e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
649e0e9324cSopenharmony_ci    keyOnly_ = enable;
650e0e9324cSopenharmony_ci}
651e0e9324cSopenharmony_ci
652e0e9324cSopenharmony_ciint32_t BufferDispatcher::AttachReceiver(BufferReceiver::Ptr receiver)
653e0e9324cSopenharmony_ci{
654e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
655e0e9324cSopenharmony_ci    if (receiver == nullptr) {
656e0e9324cSopenharmony_ci        return -1;
657e0e9324cSopenharmony_ci    }
658e0e9324cSopenharmony_ci
659e0e9324cSopenharmony_ci    if (IsRecevierExist(receiver->GetReceiverId())) {
660e0e9324cSopenharmony_ci        SHARING_LOGE("Exist.");
661e0e9324cSopenharmony_ci        return 0;
662e0e9324cSopenharmony_ci    }
663e0e9324cSopenharmony_ci
664e0e9324cSopenharmony_ci    receiver->NotifyReadStart();
665e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
666e0e9324cSopenharmony_ci    if (readRefFlag_ == 0xFFFF) {
667e0e9324cSopenharmony_ci        SHARING_LOGE("readRefFlag limited.");
668e0e9324cSopenharmony_ci        return -1;
669e0e9324cSopenharmony_ci    }
670e0e9324cSopenharmony_ci
671e0e9324cSopenharmony_ci    DataNotifier::Ptr notifier = std::make_shared<DataNotifier>();
672e0e9324cSopenharmony_ci    notifier->SetListenDispatcher(shared_from_this());
673e0e9324cSopenharmony_ci    notifier->SetNotifyReceiver(receiver);
674e0e9324cSopenharmony_ci
675e0e9324cSopenharmony_ci    auto usableRef = ~readRefFlag_ & (-(~readRefFlag_));
676e0e9324cSopenharmony_ci
677e0e9324cSopenharmony_ci    if ((usableRef & (usableRef - 1)) != 0) {
678e0e9324cSopenharmony_ci        SHARING_LOGE("usableRef: %{public}d invalid.", usableRef);
679e0e9324cSopenharmony_ci        return -1;
680e0e9324cSopenharmony_ci    }
681e0e9324cSopenharmony_ci
682e0e9324cSopenharmony_ci    readRefFlag_ |= usableRef;
683e0e9324cSopenharmony_ci    notifier->SetReadIndex(static_cast<uint32_t>(log2(usableRef)));
684e0e9324cSopenharmony_ci    SHARING_LOGI("receiverId: %{public}d, readIndex: %{public}d, usableRef: %{public}d, readRefFlag_: %{public}d.",
685e0e9324cSopenharmony_ci                 receiver->GetReceiverId(), notifier->GetReadIndex(), usableRef, readRefFlag_);
686e0e9324cSopenharmony_ci    receiver->SetSource(shared_from_this());
687e0e9324cSopenharmony_ci    notifiers_.emplace(receiver->GetReceiverId(), notifier);
688e0e9324cSopenharmony_ci
689e0e9324cSopenharmony_ci    if (circularBuffer_.empty()) {
690e0e9324cSopenharmony_ci        notifier->audioIndex = INVALID_INDEX;
691e0e9324cSopenharmony_ci        notifier->videoIndex = INVALID_INDEX;
692e0e9324cSopenharmony_ci        SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_AUDIO, false);
693e0e9324cSopenharmony_ci        SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_VIDEO, false);
694e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher Attach when buffer empty  RecvId: %{public}d.", receiver->GetReceiverId());
695e0e9324cSopenharmony_ci        videoNeedActivate_ = true;
696e0e9324cSopenharmony_ci        audioNeedActivate_ = true;
697e0e9324cSopenharmony_ci        return 0;
698e0e9324cSopenharmony_ci    }
699e0e9324cSopenharmony_ci
700e0e9324cSopenharmony_ci    if (dataMode_ == MEDIA_AUDIO_ONLY) {
701e0e9324cSopenharmony_ci        notifier->audioIndex = circularBuffer_.size() - 1;
702e0e9324cSopenharmony_ci        SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_AUDIO, true);
703e0e9324cSopenharmony_ci        notifier->videoIndex = INVALID_INDEX;
704e0e9324cSopenharmony_ci        SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_VIDEO, false);
705e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher Attach when Keyindex List empty  RecvId: %{public}d.",
706e0e9324cSopenharmony_ci                     receiver->GetReceiverId());
707e0e9324cSopenharmony_ci    } else {
708e0e9324cSopenharmony_ci        if (!keyIndexList_.empty()) {
709e0e9324cSopenharmony_ci            SHARING_LOGD("BufferDispatcher Attach with Keyindex  RecvId: %{public}d  KeyIndex:%{public}d.",
710e0e9324cSopenharmony_ci                         receiver->GetReceiverId(), keyIndexList_.back());
711e0e9324cSopenharmony_ci            uint32_t tempIndex = FindNextIndex(keyIndexList_.back(), MEDIA_TYPE_AUDIO);
712e0e9324cSopenharmony_ci            notifier->audioIndex = tempIndex == keyIndexList_.back() ? INVALID_INDEX : tempIndex;
713e0e9324cSopenharmony_ci            notifier->videoIndex = keyIndexList_.back();
714e0e9324cSopenharmony_ci            bool isAudioReady = tempIndex != INVALID_INDEX ? true : false;
715e0e9324cSopenharmony_ci            SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_AUDIO, isAudioReady);
716e0e9324cSopenharmony_ci            SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_VIDEO, true);
717e0e9324cSopenharmony_ci            if (lastAudioIndex_ == INVALID_INDEX) {
718e0e9324cSopenharmony_ci                audioNeedActivate_ = true;
719e0e9324cSopenharmony_ci            }
720e0e9324cSopenharmony_ci        } else {
721e0e9324cSopenharmony_ci            SHARING_LOGD("BufferDispatcher Attach with Non Keyindex Exist RecvId: %{public}d.",
722e0e9324cSopenharmony_ci                         receiver->GetReceiverId());
723e0e9324cSopenharmony_ci            uint32_t tempIndex = FindLastIndex(MEDIA_TYPE_AUDIO);
724e0e9324cSopenharmony_ci            notifier->audioIndex = tempIndex;
725e0e9324cSopenharmony_ci            notifier->videoIndex = INVALID_INDEX;
726e0e9324cSopenharmony_ci            SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_AUDIO, true);
727e0e9324cSopenharmony_ci            SetReceiverDataRef(receiver->GetReceiverId(), MEDIA_TYPE_VIDEO, false);
728e0e9324cSopenharmony_ci            if (lastAudioIndex_ == INVALID_INDEX) {
729e0e9324cSopenharmony_ci                audioNeedActivate_ = true;
730e0e9324cSopenharmony_ci            }
731e0e9324cSopenharmony_ci        }
732e0e9324cSopenharmony_ci    }
733e0e9324cSopenharmony_ci
734e0e9324cSopenharmony_ci    return 0;
735e0e9324cSopenharmony_ci}
736e0e9324cSopenharmony_ci
737e0e9324cSopenharmony_ciint32_t BufferDispatcher::DetachReceiver(BufferReceiver::Ptr receiver)
738e0e9324cSopenharmony_ci{
739e0e9324cSopenharmony_ci    SHARING_LOGI("buffer dispatcher: Detach receiver in.");
740e0e9324cSopenharmony_ci    if (receiver == nullptr) {
741e0e9324cSopenharmony_ci        SHARING_LOGE("buffer dispatcher: Detach receiver failed - null receiver.");
742e0e9324cSopenharmony_ci        return -1;
743e0e9324cSopenharmony_ci    }
744e0e9324cSopenharmony_ci
745e0e9324cSopenharmony_ci    if (!IsRecevierExist(receiver->GetReceiverId())) {
746e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher AttachReceiver No Vaild Recevier Exist.");
747e0e9324cSopenharmony_ci        return 0;
748e0e9324cSopenharmony_ci    }
749e0e9324cSopenharmony_ci
750e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverPtr(receiver);
751e0e9324cSopenharmony_ci    if (notifier == nullptr) {
752e0e9324cSopenharmony_ci        SHARING_LOGE("buffer dispatcher: Detach receiver failed - no find receiver in notifiers.");
753e0e9324cSopenharmony_ci        return -1;
754e0e9324cSopenharmony_ci    }
755e0e9324cSopenharmony_ci
756e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
757e0e9324cSopenharmony_ci    notifier->SetBlock();
758e0e9324cSopenharmony_ci    SetReceiverReadRef(receiver->GetReceiverId(), MEDIA_TYPE_AUDIO, false);
759e0e9324cSopenharmony_ci    SetReceiverReadRef(receiver->GetReceiverId(), MEDIA_TYPE_VIDEO, false);
760e0e9324cSopenharmony_ci
761e0e9324cSopenharmony_ci    readRefFlag_ &= ~(RECV_FLAG_BASE << notifier->GetReadIndex());
762e0e9324cSopenharmony_ci    notifiers_.erase(receiver->GetReceiverId());
763e0e9324cSopenharmony_ci    SHARING_LOGI("now refFlag: %{public}d.", readRefFlag_);
764e0e9324cSopenharmony_ci    return 0;
765e0e9324cSopenharmony_ci}
766e0e9324cSopenharmony_ci
767e0e9324cSopenharmony_ciint32_t BufferDispatcher::DetachReceiver(uint32_t receiverId, DataNotifier::Ptr notifier)
768e0e9324cSopenharmony_ci{
769e0e9324cSopenharmony_ci    SHARING_LOGI("buffer dispatcher: Detach notifier in.");
770e0e9324cSopenharmony_ci    if (notifier == nullptr) {
771e0e9324cSopenharmony_ci        SHARING_LOGE("buffer dispatcher: Detach receiver failed - null notifier.");
772e0e9324cSopenharmony_ci        return -1;
773e0e9324cSopenharmony_ci    }
774e0e9324cSopenharmony_ci    notifier->SetBlock();
775e0e9324cSopenharmony_ci    SetReceiverReadRef(receiverId, MEDIA_TYPE_AUDIO, false);
776e0e9324cSopenharmony_ci    SetReceiverReadRef(receiverId, MEDIA_TYPE_VIDEO, false);
777e0e9324cSopenharmony_ci
778e0e9324cSopenharmony_ci    readRefFlag_ &= ~(RECV_FLAG_BASE << notifier->GetReadIndex());
779e0e9324cSopenharmony_ci    notifiers_.erase(receiverId);
780e0e9324cSopenharmony_ci    SHARING_LOGI("now refFlag: %{public}d.", readRefFlag_);
781e0e9324cSopenharmony_ci    return 0;
782e0e9324cSopenharmony_ci}
783e0e9324cSopenharmony_ci
784e0e9324cSopenharmony_civoid BufferDispatcher::ReleaseAllReceiver()
785e0e9324cSopenharmony_ci{
786e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
787e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
788e0e9324cSopenharmony_ci    for (auto it = notifiers_.begin(); it != notifiers_.end();) {
789e0e9324cSopenharmony_ci        auto notifier = it->second;
790e0e9324cSopenharmony_ci        if (notifier == nullptr) {
791e0e9324cSopenharmony_ci            ++it;
792e0e9324cSopenharmony_ci            continue;
793e0e9324cSopenharmony_ci        }
794e0e9324cSopenharmony_ci
795e0e9324cSopenharmony_ci        auto receiver = notifier->GetBufferReceiver();
796e0e9324cSopenharmony_ci        if (receiver == nullptr) {
797e0e9324cSopenharmony_ci            ++it;
798e0e9324cSopenharmony_ci            continue;
799e0e9324cSopenharmony_ci        }
800e0e9324cSopenharmony_ci
801e0e9324cSopenharmony_ci        auto receiverId = receiver->GetReceiverId();
802e0e9324cSopenharmony_ci        if (notifiers_.find(receiverId) != notifiers_.end()) {
803e0e9324cSopenharmony_ci            auto notifierFind = notifiers_[receiverId];
804e0e9324cSopenharmony_ci            ++it;
805e0e9324cSopenharmony_ci            DetachReceiver(receiverId, notifierFind);
806e0e9324cSopenharmony_ci        } else {
807e0e9324cSopenharmony_ci            ++it;
808e0e9324cSopenharmony_ci            SHARING_LOGE("buffer dispatcher: Detach receiver failed - no find receiver in notifiers.");
809e0e9324cSopenharmony_ci        }
810e0e9324cSopenharmony_ci    }
811e0e9324cSopenharmony_ci
812e0e9324cSopenharmony_ci    notifiers_.clear();
813e0e9324cSopenharmony_ci    SHARING_LOGD("release all receiver out.");
814e0e9324cSopenharmony_ci}
815e0e9324cSopenharmony_ci
816e0e9324cSopenharmony_civoid BufferDispatcher::SetBufferDispatcherListener(BufferDispatcherListener::Ptr listener)
817e0e9324cSopenharmony_ci{
818e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
819e0e9324cSopenharmony_ci    listener_ = listener;
820e0e9324cSopenharmony_ci    RETURN_IF_NULL(writingTimer_);
821e0e9324cSopenharmony_ci    writingTimer_->StartTimer(
822e0e9324cSopenharmony_ci        WRITING_TIMTOUT, "waiting for continuous data inputs",
823e0e9324cSopenharmony_ci        [this]() {
824e0e9324cSopenharmony_ci            if (!writing_) {
825e0e9324cSopenharmony_ci                SHARING_LOGI("writing timeout");
826e0e9324cSopenharmony_ci                auto listener = listener_.lock();
827e0e9324cSopenharmony_ci                if (listener) {
828e0e9324cSopenharmony_ci                    listener->OnWriteTimeout();
829e0e9324cSopenharmony_ci                }
830e0e9324cSopenharmony_ci            } else {
831e0e9324cSopenharmony_ci                SHARING_LOGI("restart timer");
832e0e9324cSopenharmony_ci                writing_ = false;
833e0e9324cSopenharmony_ci            }
834e0e9324cSopenharmony_ci        },
835e0e9324cSopenharmony_ci        true);
836e0e9324cSopenharmony_ci}
837e0e9324cSopenharmony_ci
838e0e9324cSopenharmony_ciDataNotifier::Ptr BufferDispatcher::GetNotifierByReceiverPtr(BufferReceiver::Ptr receiver)
839e0e9324cSopenharmony_ci{
840e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
841e0e9324cSopenharmony_ci
842e0e9324cSopenharmony_ci    return GetNotifierByReceiverId(receiver->GetReceiverId());
843e0e9324cSopenharmony_ci}
844e0e9324cSopenharmony_ci
845e0e9324cSopenharmony_ciDataNotifier::Ptr BufferDispatcher::GetNotifierByReceiverId(uint32_t receiverId)
846e0e9324cSopenharmony_ci{
847e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
848e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
849e0e9324cSopenharmony_ci    if (notifiers_.find(receiverId) != notifiers_.end()) {
850e0e9324cSopenharmony_ci        return notifiers_[receiverId];
851e0e9324cSopenharmony_ci    }
852e0e9324cSopenharmony_ci
853e0e9324cSopenharmony_ci    return nullptr;
854e0e9324cSopenharmony_ci}
855e0e9324cSopenharmony_ci
856e0e9324cSopenharmony_ciint32_t BufferDispatcher::ReadBufferData(uint32_t receiverId, MediaType type,
857e0e9324cSopenharmony_ci                                         std::function<void(const MediaData::Ptr &data)> cb)
858e0e9324cSopenharmony_ci{
859e0e9324cSopenharmony_ci    MEDIA_LOGD("in, receiverId: %{public}u.", receiverId);
860e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverId(receiverId);
861e0e9324cSopenharmony_ci    if (notifier == nullptr) {
862e0e9324cSopenharmony_ci        SHARING_LOGE("notifier is nullptr.");
863e0e9324cSopenharmony_ci        return -1;
864e0e9324cSopenharmony_ci    }
865e0e9324cSopenharmony_ci
866e0e9324cSopenharmony_ci    std::shared_lock<std::shared_mutex> locker(bufferMutex_);
867e0e9324cSopenharmony_ci    uint32_t readIndex = notifier->GetReceiverReadIndex(type);
868e0e9324cSopenharmony_ci    if (readIndex >= circularBuffer_.size()) {
869e0e9324cSopenharmony_ci        SHARING_LOGE("Read wrong index exceed size.");
870e0e9324cSopenharmony_ci        return -1;
871e0e9324cSopenharmony_ci    }
872e0e9324cSopenharmony_ci
873e0e9324cSopenharmony_ci    if ((keyOnly_ || notifier->IsKeyModeReceiver()) && type == MEDIA_TYPE_VIDEO &&
874e0e9324cSopenharmony_ci        !IsKeyVideoFrame(circularBuffer_.at(readIndex))) {
875e0e9324cSopenharmony_ci        UpdateReceiverReadIndex(receiverId, readIndex, type);
876e0e9324cSopenharmony_ci        SHARING_LOGE("Read Non Key Video in KeyOnly Mode index: %{public}u.", readIndex);
877e0e9324cSopenharmony_ci        return -1;
878e0e9324cSopenharmony_ci    }
879e0e9324cSopenharmony_ci
880e0e9324cSopenharmony_ci    if (IsDataReaded(receiverId, circularBuffer_.at(readIndex))) {
881e0e9324cSopenharmony_ci        UpdateReceiverReadIndex(receiverId, readIndex, type);
882e0e9324cSopenharmony_ci        return -1;
883e0e9324cSopenharmony_ci    }
884e0e9324cSopenharmony_ci
885e0e9324cSopenharmony_ci    readIndex = notifier->GetReceiverReadIndex(type);
886e0e9324cSopenharmony_ci    if (readIndex >= circularBuffer_.size()) {
887e0e9324cSopenharmony_ci        return -1;
888e0e9324cSopenharmony_ci    }
889e0e9324cSopenharmony_ci
890e0e9324cSopenharmony_ci    auto data = circularBuffer_.at(readIndex);
891e0e9324cSopenharmony_ci    if (data == nullptr) {
892e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher Read data nullptr.");
893e0e9324cSopenharmony_ci        return -1;
894e0e9324cSopenharmony_ci    }
895e0e9324cSopenharmony_ci
896e0e9324cSopenharmony_ci    if (IsKeyVideoFrame(data)) {
897e0e9324cSopenharmony_ci        int32_t bufferVideoCacheCnt = 0;
898e0e9324cSopenharmony_ci        for (size_t i = readIndex + 1; i < circularBuffer_.size(); i++) {
899e0e9324cSopenharmony_ci            if (circularBuffer_[i]->mediaData->mediaType == MEDIA_TYPE_VIDEO)
900e0e9324cSopenharmony_ci                bufferVideoCacheCnt++;
901e0e9324cSopenharmony_ci        }
902e0e9324cSopenharmony_ci        MEDIA_LOGD("TEST STATISTIC:interval: buffer cache %{public}d frames.", bufferVideoCacheCnt);
903e0e9324cSopenharmony_ci    }
904e0e9324cSopenharmony_ci
905e0e9324cSopenharmony_ci    SetReceiverReadFlag(receiverId, data);
906e0e9324cSopenharmony_ci    if (cb != nullptr) {
907e0e9324cSopenharmony_ci        cb(data->mediaData);
908e0e9324cSopenharmony_ci    }
909e0e9324cSopenharmony_ci
910e0e9324cSopenharmony_ci    MEDIA_LOGD("Current data readed, Recvid:%{public}d, remain %{public}zu data, readIndex: %{public}u, "
911e0e9324cSopenharmony_ci               "readtype: %{public}d, diff: %{public}zu.",
912e0e9324cSopenharmony_ci               receiverId, circularBuffer_.size(), readIndex, int32_t(type), circularBuffer_.size() - readIndex);
913e0e9324cSopenharmony_ci    UpdateReceiverReadIndex(receiverId, readIndex, type);
914e0e9324cSopenharmony_ci    return 0;
915e0e9324cSopenharmony_ci}
916e0e9324cSopenharmony_ci
917e0e9324cSopenharmony_ciint32_t BufferDispatcher::InputData(const MediaData::Ptr &data)
918e0e9324cSopenharmony_ci{
919e0e9324cSopenharmony_ci    if (data == nullptr || data->buff == nullptr) {
920e0e9324cSopenharmony_ci        SHARING_LOGE("data nullptr.");
921e0e9324cSopenharmony_ci        return -1;
922e0e9324cSopenharmony_ci    }
923e0e9324cSopenharmony_ci    MEDIA_LOGD("inputmediatype: %{public}d, keyFrame: %{public}d, pts: %{public}" PRIu64 ".", data->mediaType,
924e0e9324cSopenharmony_ci               data->keyFrame, data->pts);
925e0e9324cSopenharmony_ci
926e0e9324cSopenharmony_ci    if (!writing_) {
927e0e9324cSopenharmony_ci        writing_ = true;
928e0e9324cSopenharmony_ci    }
929e0e9324cSopenharmony_ci
930e0e9324cSopenharmony_ci    DataSpec::Ptr dataSpec = std::make_shared<DataSpec>();
931e0e9324cSopenharmony_ci    dataSpec->mediaData = data;
932e0e9324cSopenharmony_ci    if (dataMode_ == MEDIA_AUDIO_ONLY) {
933e0e9324cSopenharmony_ci        WriteDataIntoBuffer(dataSpec);
934e0e9324cSopenharmony_ci    } else {
935e0e9324cSopenharmony_ci        PreProcessDataSpec(dataSpec);
936e0e9324cSopenharmony_ci    }
937e0e9324cSopenharmony_ci
938e0e9324cSopenharmony_ci    if (circularBuffer_.size() > 0) {
939e0e9324cSopenharmony_ci        MEDIA_LOGD("inputmediatype: %{public}d, keyFrame: %{public}d, pts: %{public}" PRIu64 ".",
940e0e9324cSopenharmony_ci                   circularBuffer_[circularBuffer_.size() - 1]->mediaData->mediaType,
941e0e9324cSopenharmony_ci                   circularBuffer_[circularBuffer_.size() - 1]->mediaData->keyFrame,
942e0e9324cSopenharmony_ci                   circularBuffer_[circularBuffer_.size() - 1]->mediaData->pts);
943e0e9324cSopenharmony_ci    }
944e0e9324cSopenharmony_ci
945e0e9324cSopenharmony_ci    if (data->keyFrame) {
946e0e9324cSopenharmony_ci        MEDIA_LOGD("dispatcherId: %{public}u, after InputData, current circularBuffer_ size: %{public}zu, "
947e0e9324cSopenharmony_ci                   "idleVideoBuffer_ size: %{public}zu, idle_audioBuffer_ size: %{public}zu, "
948e0e9324cSopenharmony_ci                   "keyFrame: %{public}s, data size: %{public}d, adataCount:%{public}d.",
949e0e9324cSopenharmony_ci                   GetDispatcherId(), circularBuffer_.size(), idleVideoBuffer_.size(), idleAudioBuffer_.size(),
950e0e9324cSopenharmony_ci                   data->keyFrame ? "true" : "false", data->buff->Size(), audioFrameCnt_);
951e0e9324cSopenharmony_ci    }
952e0e9324cSopenharmony_ci
953e0e9324cSopenharmony_ci    return 0;
954e0e9324cSopenharmony_ci}
955e0e9324cSopenharmony_ci
956e0e9324cSopenharmony_civoid BufferDispatcher::PreProcessDataSpec(const DataSpec::Ptr &dataSpec)
957e0e9324cSopenharmony_ci{
958e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
959e0e9324cSopenharmony_ci    if (waitingKey_) {
960e0e9324cSopenharmony_ci        if (IsAudioData(dataSpec)) {
961e0e9324cSopenharmony_ci        } else if (!IsKeyVideoFrame(dataSpec)) {
962e0e9324cSopenharmony_ci            SHARING_LOGD("BufferDispatcher Waiting First Key Video Frame.");
963e0e9324cSopenharmony_ci            return;
964e0e9324cSopenharmony_ci        } else {
965e0e9324cSopenharmony_ci            SHARING_LOGD("BufferDispatcher received first key video frame and restore from uncontinuous...Flushing.");
966e0e9324cSopenharmony_ci            FlushBuffer();
967e0e9324cSopenharmony_ci            baseCounter_++;
968e0e9324cSopenharmony_ci            capacityEvaluating_ = true;
969e0e9324cSopenharmony_ci            waitingKey_ = false;
970e0e9324cSopenharmony_ci        }
971e0e9324cSopenharmony_ci    } else {
972e0e9324cSopenharmony_ci        if (capacityEvaluating_) {
973e0e9324cSopenharmony_ci            ReCalculateCapacity(IsKeyVideoFrame(dataSpec));
974e0e9324cSopenharmony_ci        }
975e0e9324cSopenharmony_ci    }
976e0e9324cSopenharmony_ci
977e0e9324cSopenharmony_ci    WriteDataIntoBuffer(dataSpec);
978e0e9324cSopenharmony_ci}
979e0e9324cSopenharmony_ci
980e0e9324cSopenharmony_ciint32_t BufferDispatcher::WriteDataIntoBuffer(const DataSpec::Ptr &data)
981e0e9324cSopenharmony_ci{
982e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
983e0e9324cSopenharmony_ci    if (data->mediaData == nullptr || data->mediaData->buff == nullptr) {
984e0e9324cSopenharmony_ci        SHARING_LOGE("null data.");
985e0e9324cSopenharmony_ci        return -1;
986e0e9324cSopenharmony_ci    }
987e0e9324cSopenharmony_ci
988e0e9324cSopenharmony_ci    if (NeedExtendToDBCapacity()) {
989e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher buffer Extended to %{public}d  CRTL_SIZE.", doubleBufferCapacity_);
990e0e9324cSopenharmony_ci        SetBufferCapacity(doubleBufferCapacity_);
991e0e9324cSopenharmony_ci    }
992e0e9324cSopenharmony_ci
993e0e9324cSopenharmony_ci    if (NeedRestoreToNormalCapacity()) {
994e0e9324cSopenharmony_ci        std::unique_lock<std::shared_mutex> locker(bufferMutex_);
995e0e9324cSopenharmony_ci        int32_t popSize = circularBuffer_.size() - INITIAL_BUFFER_CAPACITY;
996e0e9324cSopenharmony_ci        for (int32_t i = 0; i < popSize; i++) {
997e0e9324cSopenharmony_ci            if (HeadFrameNeedReserve()) {
998e0e9324cSopenharmony_ci                MEDIA_LOGW("dispatcherId: %{public}u, need reserve but pop, mediaType: "
999e0e9324cSopenharmony_ci                           "%{public}d, keyFrame: %{public}s, pts: %{public}" PRIu64 ".",
1000e0e9324cSopenharmony_ci                           GetDispatcherId(), int32_t(circularBuffer_.front()->mediaData->mediaType),
1001e0e9324cSopenharmony_ci                           circularBuffer_.front()->mediaData->keyFrame ? "true" : "false",
1002e0e9324cSopenharmony_ci                           circularBuffer_.front()->mediaData->pts);
1003e0e9324cSopenharmony_ci            }
1004e0e9324cSopenharmony_ci
1005e0e9324cSopenharmony_ci            MEDIA_LOGW("dispatcherId: %{public}u, delete data, mediaType: %{public}d, keyFrame: "
1006e0e9324cSopenharmony_ci                       "%{public}s, pts: %{public}" PRIu64 ", reserveFlag: %{public}x.",
1007e0e9324cSopenharmony_ci                       GetDispatcherId(), int32_t(circularBuffer_.front()->mediaData->mediaType),
1008e0e9324cSopenharmony_ci                       circularBuffer_.front()->mediaData->keyFrame ? "true" : "false",
1009e0e9324cSopenharmony_ci                       circularBuffer_.front()->mediaData->pts, circularBuffer_.front()->reserveFlag.load());
1010e0e9324cSopenharmony_ci            circularBuffer_.pop_front();
1011e0e9324cSopenharmony_ci            audioFrameCnt_--;
1012e0e9324cSopenharmony_ci            UpdateIndex();
1013e0e9324cSopenharmony_ci        }
1014e0e9324cSopenharmony_ci
1015e0e9324cSopenharmony_ci        baseBufferCapacity_ = INITIAL_BUFFER_CAPACITY;
1016e0e9324cSopenharmony_ci        doubleBufferCapacity_ = INITIAL_BUFFER_CAPACITY * 2; // 2 : increasement
1017e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher buffer Extended to %{public}d  NORMALSIZE.", baseBufferCapacity_);
1018e0e9324cSopenharmony_ci        circularBuffer_.set_capacity(baseBufferCapacity_);
1019e0e9324cSopenharmony_ci    }
1020e0e9324cSopenharmony_ci
1021e0e9324cSopenharmony_ci    if (IsKeyVideoFrame(data) && !keyOnly_) {
1022e0e9324cSopenharmony_ci        EraseOldGopDatas();
1023e0e9324cSopenharmony_ci    }
1024e0e9324cSopenharmony_ci
1025e0e9324cSopenharmony_ci    bool updateIndexFlag = false;
1026e0e9324cSopenharmony_ci    std::unique_lock<std::shared_mutex> locker(bufferMutex_);
1027e0e9324cSopenharmony_ci    if (circularBuffer_.size() >= circularBuffer_.capacity()) {
1028e0e9324cSopenharmony_ci        updateIndexFlag = true;
1029e0e9324cSopenharmony_ci    }
1030e0e9324cSopenharmony_ci
1031e0e9324cSopenharmony_ci    if (updateIndexFlag) {
1032e0e9324cSopenharmony_ci        uint32_t nextDeleteIndex = 1;
1033e0e9324cSopenharmony_ci        if (IsVideoData(data)) {
1034e0e9324cSopenharmony_ci            nextDeleteIndex = FindNextDeleteVideoIndex();
1035e0e9324cSopenharmony_ci        }
1036e0e9324cSopenharmony_ci
1037e0e9324cSopenharmony_ci        for (size_t i = 0; i <= nextDeleteIndex; i++) {
1038e0e9324cSopenharmony_ci            MediaType headType = circularBuffer_.front()->mediaData->mediaType;
1039e0e9324cSopenharmony_ci            DataSpec::Ptr retBuff = circularBuffer_.front();
1040e0e9324cSopenharmony_ci            if (HeadFrameNeedReserve()) {
1041e0e9324cSopenharmony_ci                MEDIA_LOGW("dispatcherId: %{public}u, need reserve but pop, mediaType: "
1042e0e9324cSopenharmony_ci                           "%{public}d, keyFrame: %{public}s, pts: %{public}" PRIu64 ".",
1043e0e9324cSopenharmony_ci                           GetDispatcherId(), int32_t(retBuff->mediaData->mediaType),
1044e0e9324cSopenharmony_ci                           retBuff->mediaData->keyFrame ? "true" : "false", retBuff->mediaData->pts);
1045e0e9324cSopenharmony_ci            }
1046e0e9324cSopenharmony_ci
1047e0e9324cSopenharmony_ci            MEDIA_LOGW("dispatcherId: %{public}u, delete data, mediaType: %{public}d, "
1048e0e9324cSopenharmony_ci                       "keyFrame: %{public}s, pts: %{public}" PRIu64 ", reserveFlag: %{public}x.",
1049e0e9324cSopenharmony_ci                       GetDispatcherId(), int32_t(circularBuffer_.front()->mediaData->mediaType),
1050e0e9324cSopenharmony_ci                       circularBuffer_.front()->mediaData->keyFrame ? "true" : "false",
1051e0e9324cSopenharmony_ci                       circularBuffer_.front()->mediaData->pts, circularBuffer_.front()->reserveFlag.load());
1052e0e9324cSopenharmony_ci
1053e0e9324cSopenharmony_ci            circularBuffer_.pop_front();
1054e0e9324cSopenharmony_ci            ReturnIdleBuffer(retBuff);
1055e0e9324cSopenharmony_ci            headType == MEDIA_TYPE_AUDIO ? audioFrameCnt_-- : videoFrameCnt_--;
1056e0e9324cSopenharmony_ci            UpdateIndex();
1057e0e9324cSopenharmony_ci        }
1058e0e9324cSopenharmony_ci    }
1059e0e9324cSopenharmony_ci
1060e0e9324cSopenharmony_ci    data->reserveFlag = 0;
1061e0e9324cSopenharmony_ci    MEDIA_LOGD("WriteDataIntoBuffer data type: %{public}d, keyFrame: %{public}s, pts: %{public}" PRIu64
1062e0e9324cSopenharmony_ci               ", cur_size: %{public}zu, capacity: %{public}zu dispatcher[%{public}u].",
1063e0e9324cSopenharmony_ci               int32_t(data->mediaData->mediaType), data->mediaData->keyFrame ? "true" : "false", data->mediaData->pts,
1064e0e9324cSopenharmony_ci               circularBuffer_.size(), circularBuffer_.capacity(), GetDispatcherId());
1065e0e9324cSopenharmony_ci    circularBuffer_.push_back(data);
1066e0e9324cSopenharmony_ci    if (IsAudioData(data)) {
1067e0e9324cSopenharmony_ci        lastAudioIndex_ = circularBuffer_.size() - 1;
1068e0e9324cSopenharmony_ci        ActiveDataRef(MEDIA_TYPE_AUDIO, false);
1069e0e9324cSopenharmony_ci        audioFrameCnt_++;
1070e0e9324cSopenharmony_ci    } else {
1071e0e9324cSopenharmony_ci        lastVideoIndex_ = circularBuffer_.size() - 1;
1072e0e9324cSopenharmony_ci        if (!keyOnly_ || (keyOnly_ && IsKeyVideoFrame(data))) {
1073e0e9324cSopenharmony_ci            ActiveDataRef(MEDIA_TYPE_VIDEO, IsKeyVideoFrame(data));
1074e0e9324cSopenharmony_ci        }
1075e0e9324cSopenharmony_ci        videoFrameCnt_++;
1076e0e9324cSopenharmony_ci    }
1077e0e9324cSopenharmony_ci
1078e0e9324cSopenharmony_ci    if (audioNeedActivate_ && IsAudioData(data)) {
1079e0e9324cSopenharmony_ci        MEDIA_LOGD("BufferDispatcher ActivateReceiverIndex By AudioData.");
1080e0e9324cSopenharmony_ci        ActivateReceiverIndex(circularBuffer_.size() - 1, MEDIA_TYPE_AUDIO);
1081e0e9324cSopenharmony_ci    }
1082e0e9324cSopenharmony_ci
1083e0e9324cSopenharmony_ci    if (IsKeyVideoFrame(data)) {
1084e0e9324cSopenharmony_ci        uint32_t keyIndex = circularBuffer_.size() - 1;
1085e0e9324cSopenharmony_ci        {
1086e0e9324cSopenharmony_ci            std::lock_guard<std::mutex> indexLocker(notifyMutex_);
1087e0e9324cSopenharmony_ci            keyIndexList_.push_back(keyIndex);
1088e0e9324cSopenharmony_ci        }
1089e0e9324cSopenharmony_ci        if (videoNeedActivate_) {
1090e0e9324cSopenharmony_ci            MEDIA_LOGD("BufferDispatcher ActivateReceiverIndex By KeyVideo Frame index: %{public}d.", keyIndex);
1091e0e9324cSopenharmony_ci            ActivateReceiverIndex(keyIndex, MEDIA_TYPE_VIDEO);
1092e0e9324cSopenharmony_ci        }
1093e0e9324cSopenharmony_ci        if (keyRedirect_) {
1094e0e9324cSopenharmony_ci            OnKeyRedirect();
1095e0e9324cSopenharmony_ci            EnableKeyRedirect(false);
1096e0e9324cSopenharmony_ci        }
1097e0e9324cSopenharmony_ci    }
1098e0e9324cSopenharmony_ci
1099e0e9324cSopenharmony_ci    continueNotify_ = true;
1100e0e9324cSopenharmony_ci    dataCV_.notify_one();
1101e0e9324cSopenharmony_ci    return 0;
1102e0e9324cSopenharmony_ci}
1103e0e9324cSopenharmony_ci
1104e0e9324cSopenharmony_civoid BufferDispatcher::EraseOldGopDatas()
1105e0e9324cSopenharmony_ci{
1106e0e9324cSopenharmony_ci    MEDIA_LOGD("BufferDispatcher Delete old datas In.");
1107e0e9324cSopenharmony_ci    if (dataMode_ == MEDIA_AUDIO_ONLY) {
1108e0e9324cSopenharmony_ci        FlushBuffer();
1109e0e9324cSopenharmony_ci        return;
1110e0e9324cSopenharmony_ci    }
1111e0e9324cSopenharmony_ci
1112e0e9324cSopenharmony_ci    std::unique_lock<std::shared_mutex> locker(bufferMutex_);
1113e0e9324cSopenharmony_ci    uint32_t nextKey = 0;
1114e0e9324cSopenharmony_ci    {
1115e0e9324cSopenharmony_ci        std::lock_guard<std::mutex> lock(notifyMutex_);
1116e0e9324cSopenharmony_ci        if (!keyIndexList_.empty() && keyIndexList_.back() > 0) {
1117e0e9324cSopenharmony_ci            MEDIA_LOGD("find next key listsize %{public}zu, back:%{public}d.", keyIndexList_.size(),
1118e0e9324cSopenharmony_ci                       keyIndexList_.back());
1119e0e9324cSopenharmony_ci            nextKey = keyIndexList_.back();
1120e0e9324cSopenharmony_ci            keyIndexList_.clear();
1121e0e9324cSopenharmony_ci            keyIndexList_.push_back(nextKey);
1122e0e9324cSopenharmony_ci        }
1123e0e9324cSopenharmony_ci    }
1124e0e9324cSopenharmony_ci
1125e0e9324cSopenharmony_ci    MEDIA_LOGD("erase between 0 to next Video Frame %{public}d.", nextKey);
1126e0e9324cSopenharmony_ci    DeleteHeadDatas(nextKey, false);
1127e0e9324cSopenharmony_ci    nextKey = FindNextDeleteVideoIndex();
1128e0e9324cSopenharmony_ci    DeleteHeadDatas(nextKey, true);
1129e0e9324cSopenharmony_ci    std::string indexs;
1130e0e9324cSopenharmony_ci
1131e0e9324cSopenharmony_ci    MEDIA_LOGD("circularBuffer_ size: %{public}zu.", circularBuffer_.size());
1132e0e9324cSopenharmony_ci    for (auto &keyIndex : keyIndexList_) {
1133e0e9324cSopenharmony_ci        indexs += std::to_string(keyIndex) + ", ";
1134e0e9324cSopenharmony_ci        MEDIA_LOGD("keyIndex update to %{public}d.", keyIndex);
1135e0e9324cSopenharmony_ci    }
1136e0e9324cSopenharmony_ci
1137e0e9324cSopenharmony_ci    MEDIA_LOGD("current keyIndex: %{public}s.", indexs.c_str());
1138e0e9324cSopenharmony_ci}
1139e0e9324cSopenharmony_ci
1140e0e9324cSopenharmony_civoid BufferDispatcher::DeleteHeadDatas(uint32_t size, bool forceDelete)
1141e0e9324cSopenharmony_ci{
1142e0e9324cSopenharmony_ci    SHARING_LOGI("%{public}s, size %{public}d.", __FUNCTION__, size);
1143e0e9324cSopenharmony_ci    if (size <= 0) {
1144e0e9324cSopenharmony_ci        MEDIA_LOGW("invalid Size, dispatcherId: %{public}u!", GetDispatcherId());
1145e0e9324cSopenharmony_ci        return;
1146e0e9324cSopenharmony_ci    }
1147e0e9324cSopenharmony_ci
1148e0e9324cSopenharmony_ci    for (size_t i = 0; i < size; i++) {
1149e0e9324cSopenharmony_ci        if (HeadFrameNeedReserve() && !forceDelete) {
1150e0e9324cSopenharmony_ci            MEDIA_LOGD("index %{public}zu need reserve.", i);
1151e0e9324cSopenharmony_ci            break;
1152e0e9324cSopenharmony_ci        }
1153e0e9324cSopenharmony_ci        if (circularBuffer_.empty()) {
1154e0e9324cSopenharmony_ci            return;
1155e0e9324cSopenharmony_ci        }
1156e0e9324cSopenharmony_ci        DataSpec::Ptr retBuff = circularBuffer_.front();
1157e0e9324cSopenharmony_ci        MEDIA_LOGD("BufferDispatcher pop out headtype  %{public}d.", retBuff->mediaData->mediaType);
1158e0e9324cSopenharmony_ci        retBuff->mediaData->mediaType == MEDIA_TYPE_AUDIO ? audioFrameCnt_-- : videoFrameCnt_--;
1159e0e9324cSopenharmony_ci        if (HeadFrameNeedReserve()) {
1160e0e9324cSopenharmony_ci            MEDIA_LOGW("dispatcherId: %{public}u, need reserve but pop, mediaType: "
1161e0e9324cSopenharmony_ci                       "%{public}d, keyFrame: %{public}s, pts: %{public}" PRIu64 ".",
1162e0e9324cSopenharmony_ci                       GetDispatcherId(), int32_t(retBuff->mediaData->mediaType),
1163e0e9324cSopenharmony_ci                       retBuff->mediaData->keyFrame ? "true" : "false", retBuff->mediaData->pts);
1164e0e9324cSopenharmony_ci        }
1165e0e9324cSopenharmony_ci
1166e0e9324cSopenharmony_ci        MEDIA_LOGD(
1167e0e9324cSopenharmony_ci            "dispatcherId: %{public}u, delete data, mediaType: %{public}d, keyFrame: %{public}s, pts: %{public}" PRIu64
1168e0e9324cSopenharmony_ci            ", reserveFlag: %{public}x.",
1169e0e9324cSopenharmony_ci            GetDispatcherId(), int32_t(circularBuffer_.front()->mediaData->mediaType),
1170e0e9324cSopenharmony_ci            circularBuffer_.front()->mediaData->keyFrame ? "true" : "false", circularBuffer_.front()->mediaData->pts,
1171e0e9324cSopenharmony_ci            circularBuffer_.front()->reserveFlag.load());
1172e0e9324cSopenharmony_ci        circularBuffer_.pop_front();
1173e0e9324cSopenharmony_ci        ReturnIdleBuffer(retBuff);
1174e0e9324cSopenharmony_ci        UpdateIndex();
1175e0e9324cSopenharmony_ci    }
1176e0e9324cSopenharmony_ci
1177e0e9324cSopenharmony_ci    if (circularBuffer_.size() < baseBufferCapacity_ && circularBuffer_.capacity() > baseBufferCapacity_) {
1178e0e9324cSopenharmony_ci        MEDIA_LOGE("capacity return to base %{public}d.", baseBufferCapacity_);
1179e0e9324cSopenharmony_ci        circularBuffer_.set_capacity(baseBufferCapacity_);
1180e0e9324cSopenharmony_ci    }
1181e0e9324cSopenharmony_ci}
1182e0e9324cSopenharmony_ci
1183e0e9324cSopenharmony_civoid BufferDispatcher::UpdateIndex()
1184e0e9324cSopenharmony_ci{
1185e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1186e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
1187e0e9324cSopenharmony_ci    if (!keyIndexList_.empty() && keyIndexList_.front() == 0) {
1188e0e9324cSopenharmony_ci        keyIndexList_.pop_front();
1189e0e9324cSopenharmony_ci        MEDIA_LOGD("BufferDispatcher pop out first  0 keyIndex after listsize %{public}zu.", keyIndexList_.size());
1190e0e9324cSopenharmony_ci    }
1191e0e9324cSopenharmony_ci
1192e0e9324cSopenharmony_ci    for (auto &keyIndex : keyIndexList_) {
1193e0e9324cSopenharmony_ci        if (keyIndex > 0) {
1194e0e9324cSopenharmony_ci            keyIndex--;
1195e0e9324cSopenharmony_ci        }
1196e0e9324cSopenharmony_ci    }
1197e0e9324cSopenharmony_ci
1198e0e9324cSopenharmony_ci    for (auto &[recvId, notifier] : notifiers_) {
1199e0e9324cSopenharmony_ci        if (notifier->videoIndex > 0 && notifier->videoIndex != INVALID_INDEX) {
1200e0e9324cSopenharmony_ci            notifier->videoIndex--;
1201e0e9324cSopenharmony_ci        }
1202e0e9324cSopenharmony_ci        if (notifier->audioIndex > 0 && notifier->audioIndex != INVALID_INDEX) {
1203e0e9324cSopenharmony_ci            notifier->audioIndex--;
1204e0e9324cSopenharmony_ci        }
1205e0e9324cSopenharmony_ci    }
1206e0e9324cSopenharmony_ci
1207e0e9324cSopenharmony_ci    if (lastVideoIndex_ > 0 && lastVideoIndex_ != INVALID_INDEX) {
1208e0e9324cSopenharmony_ci        lastVideoIndex_--;
1209e0e9324cSopenharmony_ci    }
1210e0e9324cSopenharmony_ci
1211e0e9324cSopenharmony_ci    if (lastAudioIndex_ > 0 && lastAudioIndex_ != INVALID_INDEX) {
1212e0e9324cSopenharmony_ci        lastAudioIndex_--;
1213e0e9324cSopenharmony_ci    }
1214e0e9324cSopenharmony_ci}
1215e0e9324cSopenharmony_ci
1216e0e9324cSopenharmony_ciuint32_t BufferDispatcher::FindNextDeleteVideoIndex()
1217e0e9324cSopenharmony_ci{
1218e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1219e0e9324cSopenharmony_ci    for (size_t i = 0; i < circularBuffer_.size(); i++) {
1220e0e9324cSopenharmony_ci        if (circularBuffer_[i]->mediaData != nullptr && circularBuffer_[i]->mediaData->mediaType == MEDIA_TYPE_VIDEO) {
1221e0e9324cSopenharmony_ci            return i;
1222e0e9324cSopenharmony_ci        }
1223e0e9324cSopenharmony_ci    }
1224e0e9324cSopenharmony_ci
1225e0e9324cSopenharmony_ci    return 0;
1226e0e9324cSopenharmony_ci}
1227e0e9324cSopenharmony_ci
1228e0e9324cSopenharmony_ciuint32_t BufferDispatcher::FindLastIndex(MediaType type)
1229e0e9324cSopenharmony_ci{
1230e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1231e0e9324cSopenharmony_ci    if (circularBuffer_.empty()) {
1232e0e9324cSopenharmony_ci        return INVALID_INDEX;
1233e0e9324cSopenharmony_ci    }
1234e0e9324cSopenharmony_ci
1235e0e9324cSopenharmony_ci    return type == MEDIA_TYPE_AUDIO ? lastAudioIndex_ : lastVideoIndex_;
1236e0e9324cSopenharmony_ci}
1237e0e9324cSopenharmony_ci
1238e0e9324cSopenharmony_civoid BufferDispatcher::UpdateReceiverReadIndex(uint32_t receiverId, const uint32_t readIndex, MediaType type)
1239e0e9324cSopenharmony_ci{
1240e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1241e0e9324cSopenharmony_ci    uint32_t nextIndex = FindNextIndex(readIndex, type, receiverId);
1242e0e9324cSopenharmony_ci    bool noAvaliableData = false;
1243e0e9324cSopenharmony_ci    if (nextIndex == readIndex) {
1244e0e9324cSopenharmony_ci        noAvaliableData = true;
1245e0e9324cSopenharmony_ci    }
1246e0e9324cSopenharmony_ci
1247e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverId(receiverId);
1248e0e9324cSopenharmony_ci    if (notifier == nullptr) {
1249e0e9324cSopenharmony_ci        SHARING_LOGE("notifier is nullptr.");
1250e0e9324cSopenharmony_ci        return;
1251e0e9324cSopenharmony_ci    }
1252e0e9324cSopenharmony_ci
1253e0e9324cSopenharmony_ci    bool readOver = circularBuffer_.size() - readIndex < 3;
1254e0e9324cSopenharmony_ci    if (readOver && notifier->NeedAcceleration() && type == MEDIA_TYPE_VIDEO) {
1255e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher SendAccelerationDone.");
1256e0e9324cSopenharmony_ci        notifier->SendAccelerationDone();
1257e0e9324cSopenharmony_ci    }
1258e0e9324cSopenharmony_ci
1259e0e9324cSopenharmony_ci    notifier->SetNeedUpdate(noAvaliableData, type);
1260e0e9324cSopenharmony_ci
1261e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_VIDEO) {
1262e0e9324cSopenharmony_ci        notifier->videoIndex = nextIndex;
1263e0e9324cSopenharmony_ci    } else if (type == MEDIA_TYPE_AUDIO) {
1264e0e9324cSopenharmony_ci        notifier->audioIndex = nextIndex;
1265e0e9324cSopenharmony_ci    } else {
1266e0e9324cSopenharmony_ci        notifier->videoIndex = nextIndex;
1267e0e9324cSopenharmony_ci        notifier->audioIndex = nextIndex;
1268e0e9324cSopenharmony_ci    }
1269e0e9324cSopenharmony_ci
1270e0e9324cSopenharmony_ci    MEDIA_LOGD("After UpdateReceiverReadIndex  type %{public}d, aindex %{public}d, vindex %{public}d.", type,
1271e0e9324cSopenharmony_ci               notifier->audioIndex, notifier->videoIndex);
1272e0e9324cSopenharmony_ci}
1273e0e9324cSopenharmony_ci
1274e0e9324cSopenharmony_ciuint32_t BufferDispatcher::FindNextIndex(uint32_t index, MediaType type)
1275e0e9324cSopenharmony_ci{
1276e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1277e0e9324cSopenharmony_ci    if (index + 1 >= circularBuffer_.size() || index == INVALID_INDEX) {
1278e0e9324cSopenharmony_ci        return index;
1279e0e9324cSopenharmony_ci    }
1280e0e9324cSopenharmony_ci
1281e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AV) {
1282e0e9324cSopenharmony_ci        return index + 1;
1283e0e9324cSopenharmony_ci    }
1284e0e9324cSopenharmony_ci
1285e0e9324cSopenharmony_ci    for (size_t i = index + 1; i < circularBuffer_.size(); i++) {
1286e0e9324cSopenharmony_ci        if (circularBuffer_[i] && circularBuffer_[i]->mediaData && circularBuffer_[i]->mediaData->mediaType == type) {
1287e0e9324cSopenharmony_ci            if (keyOnly_ && type == MEDIA_TYPE_VIDEO && !IsKeyVideoFrame(circularBuffer_[i])) {
1288e0e9324cSopenharmony_ci                continue;
1289e0e9324cSopenharmony_ci            } else {
1290e0e9324cSopenharmony_ci                return i;
1291e0e9324cSopenharmony_ci            }
1292e0e9324cSopenharmony_ci        }
1293e0e9324cSopenharmony_ci    }
1294e0e9324cSopenharmony_ci
1295e0e9324cSopenharmony_ci    return index;
1296e0e9324cSopenharmony_ci}
1297e0e9324cSopenharmony_ci
1298e0e9324cSopenharmony_ciuint32_t BufferDispatcher::FindNextIndex(uint32_t index, MediaType type, uint32_t receiverId)
1299e0e9324cSopenharmony_ci{
1300e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1301e0e9324cSopenharmony_ci    if (index + 1 >= circularBuffer_.size() || index == INVALID_INDEX) {
1302e0e9324cSopenharmony_ci        return index;
1303e0e9324cSopenharmony_ci    }
1304e0e9324cSopenharmony_ci
1305e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AV) {
1306e0e9324cSopenharmony_ci        return index + 1;
1307e0e9324cSopenharmony_ci    }
1308e0e9324cSopenharmony_ci
1309e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverId(receiverId);
1310e0e9324cSopenharmony_ci    if (notifier == nullptr) {
1311e0e9324cSopenharmony_ci        SHARING_LOGE("FindNextIndex GetNotifier nullptr.");
1312e0e9324cSopenharmony_ci        return INVALID_INDEX;
1313e0e9324cSopenharmony_ci    }
1314e0e9324cSopenharmony_ci
1315e0e9324cSopenharmony_ci    bool keyModeReceiver = notifier->IsKeyModeReceiver();
1316e0e9324cSopenharmony_ci    for (size_t i = index + 1; i < circularBuffer_.size(); i++) {
1317e0e9324cSopenharmony_ci        if (circularBuffer_[i] && circularBuffer_[i]->mediaData && circularBuffer_[i]->mediaData->mediaType == type) {
1318e0e9324cSopenharmony_ci            if ((keyOnly_ || keyModeReceiver) && type == MEDIA_TYPE_VIDEO) {
1319e0e9324cSopenharmony_ci                if (!IsKeyVideoFrame(circularBuffer_[i])) {
1320e0e9324cSopenharmony_ci                    continue;
1321e0e9324cSopenharmony_ci                } else {
1322e0e9324cSopenharmony_ci                    for (size_t bIndex = index + 1; bIndex < i; bIndex++) {
1323e0e9324cSopenharmony_ci                        SetReceiverReadFlag(receiverId, circularBuffer_[bIndex]);
1324e0e9324cSopenharmony_ci                    }
1325e0e9324cSopenharmony_ci                    return i;
1326e0e9324cSopenharmony_ci                }
1327e0e9324cSopenharmony_ci            } else {
1328e0e9324cSopenharmony_ci                return i;
1329e0e9324cSopenharmony_ci            }
1330e0e9324cSopenharmony_ci        }
1331e0e9324cSopenharmony_ci    }
1332e0e9324cSopenharmony_ci
1333e0e9324cSopenharmony_ci    return index;
1334e0e9324cSopenharmony_ci}
1335e0e9324cSopenharmony_ci
1336e0e9324cSopenharmony_civoid BufferDispatcher::ResetAllIndex()
1337e0e9324cSopenharmony_ci{
1338e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1339e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> locker(notifyMutex_);
1340e0e9324cSopenharmony_ci    keyIndexList_.clear();
1341e0e9324cSopenharmony_ci    for (auto &[recvId, notifier] : notifiers_) {
1342e0e9324cSopenharmony_ci        notifier->videoIndex = INVALID_INDEX;
1343e0e9324cSopenharmony_ci        notifier->audioIndex = INVALID_INDEX;
1344e0e9324cSopenharmony_ci    }
1345e0e9324cSopenharmony_ci
1346e0e9324cSopenharmony_ci    videoNeedActivate_ = true;
1347e0e9324cSopenharmony_ci    audioNeedActivate_ = true;
1348e0e9324cSopenharmony_ci    lastAudioIndex_ = INVALID_INDEX;
1349e0e9324cSopenharmony_ci    lastVideoIndex_ = INVALID_INDEX;
1350e0e9324cSopenharmony_ci}
1351e0e9324cSopenharmony_ci
1352e0e9324cSopenharmony_cibool BufferDispatcher::IsDataReaded(uint32_t receiverId, DataSpec::Ptr &dataSpec)
1353e0e9324cSopenharmony_ci{
1354e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1355e0e9324cSopenharmony_ci    uint32_t index = FindReceiverIndex(receiverId);
1356e0e9324cSopenharmony_ci    if (index == INVALID_INDEX) {
1357e0e9324cSopenharmony_ci        return false;
1358e0e9324cSopenharmony_ci    }
1359e0e9324cSopenharmony_ci
1360e0e9324cSopenharmony_ci    return dataSpec->reserveFlag & RECV_FLAG_BASE << index;
1361e0e9324cSopenharmony_ci}
1362e0e9324cSopenharmony_ci
1363e0e9324cSopenharmony_cibool BufferDispatcher::IsVideoData(const DataSpec::Ptr &dataSpec)
1364e0e9324cSopenharmony_ci{
1365e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1366e0e9324cSopenharmony_ci    if (dataSpec == nullptr || dataSpec->mediaData == nullptr) {
1367e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher EMPTY dataSpec OR mediadata.");
1368e0e9324cSopenharmony_ci        return false;
1369e0e9324cSopenharmony_ci    }
1370e0e9324cSopenharmony_ci
1371e0e9324cSopenharmony_ci    return dataSpec->mediaData->mediaType == MEDIA_TYPE_VIDEO;
1372e0e9324cSopenharmony_ci}
1373e0e9324cSopenharmony_ci
1374e0e9324cSopenharmony_cibool BufferDispatcher::IsAudioData(const DataSpec::Ptr &dataSpec)
1375e0e9324cSopenharmony_ci{
1376e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1377e0e9324cSopenharmony_ci    if (dataSpec == nullptr || dataSpec->mediaData == nullptr) {
1378e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher EMPTY dataSpec OR mediadata.");
1379e0e9324cSopenharmony_ci        return false;
1380e0e9324cSopenharmony_ci    }
1381e0e9324cSopenharmony_ci
1382e0e9324cSopenharmony_ci    return dataSpec->mediaData->mediaType == MEDIA_TYPE_AUDIO;
1383e0e9324cSopenharmony_ci}
1384e0e9324cSopenharmony_ci
1385e0e9324cSopenharmony_cibool BufferDispatcher::IsKeyVideoFrame(const DataSpec::Ptr &dataSpec)
1386e0e9324cSopenharmony_ci{
1387e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1388e0e9324cSopenharmony_ci    if (dataSpec == nullptr || dataSpec->mediaData == nullptr) {
1389e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher EMPTY dataSpec OR mediadata.");
1390e0e9324cSopenharmony_ci        return false;
1391e0e9324cSopenharmony_ci    }
1392e0e9324cSopenharmony_ci
1393e0e9324cSopenharmony_ci    return IsVideoData(dataSpec) && dataSpec->mediaData->keyFrame;
1394e0e9324cSopenharmony_ci}
1395e0e9324cSopenharmony_ci
1396e0e9324cSopenharmony_cibool BufferDispatcher::HeadFrameNeedReserve()
1397e0e9324cSopenharmony_ci{
1398e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1399e0e9324cSopenharmony_ci    if (!circularBuffer_.empty()) {
1400e0e9324cSopenharmony_ci        uint8_t temp = readRefFlag_;
1401e0e9324cSopenharmony_ci        MEDIA_LOGD("IsHeadFrameNeedReserve Head reserveFlag %{public}d readRefFlag_ %{public}d.",
1402e0e9324cSopenharmony_ci                   circularBuffer_.front()->reserveFlag.load(), readRefFlag_);
1403e0e9324cSopenharmony_ci        return temp ^ circularBuffer_.front()->reserveFlag;
1404e0e9324cSopenharmony_ci    }
1405e0e9324cSopenharmony_ci
1406e0e9324cSopenharmony_ci    return false;
1407e0e9324cSopenharmony_ci}
1408e0e9324cSopenharmony_ci
1409e0e9324cSopenharmony_cibool BufferDispatcher::NeedExtendToDBCapacity()
1410e0e9324cSopenharmony_ci{
1411e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1412e0e9324cSopenharmony_ci    std::shared_lock<std::shared_mutex> locker(bufferMutex_);
1413e0e9324cSopenharmony_ci    return (circularBuffer_.size() >= circularBuffer_.capacity() &&
1414e0e9324cSopenharmony_ci            circularBuffer_.capacity() < doubleBufferCapacity_ && HeadFrameNeedReserve());
1415e0e9324cSopenharmony_ci}
1416e0e9324cSopenharmony_ci
1417e0e9324cSopenharmony_cibool BufferDispatcher::NeedRestoreToNormalCapacity()
1418e0e9324cSopenharmony_ci{
1419e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1420e0e9324cSopenharmony_ci    std::shared_lock<std::shared_mutex> locker(bufferMutex_);
1421e0e9324cSopenharmony_ci    return audioFrameCnt_ >= circularBuffer_.capacity() && circularBuffer_.capacity() != INITIAL_BUFFER_CAPACITY;
1422e0e9324cSopenharmony_ci}
1423e0e9324cSopenharmony_ci
1424e0e9324cSopenharmony_civoid BufferDispatcher::ReCalculateCapacity(bool keyFrame)
1425e0e9324cSopenharmony_ci{
1426e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1427e0e9324cSopenharmony_ci    baseCounter_++;
1428e0e9324cSopenharmony_ci    if (baseCounter_ >= maxBufferCapacity_) {
1429e0e9324cSopenharmony_ci        SHARING_LOGE("BufferDispatcher too many Audiodata need Set Capacity to default.");
1430e0e9324cSopenharmony_ci    }
1431e0e9324cSopenharmony_ci
1432e0e9324cSopenharmony_ci    if (baseCounter_ >= circularBuffer_.capacity() && !keyFrame) {
1433e0e9324cSopenharmony_ci        uint32_t tmpSize = circularBuffer_.capacity() + bufferCapacityIncrement_ < maxBufferCapacity_
1434e0e9324cSopenharmony_ci                               ? circularBuffer_.capacity() + bufferCapacityIncrement_
1435e0e9324cSopenharmony_ci                               : maxBufferCapacity_;
1436e0e9324cSopenharmony_ci        doubleBufferCapacity_ = tmpSize * 2 < maxBufferCapacity_ ? tmpSize * 2 : maxBufferCapacity_; // 2: increasement
1437e0e9324cSopenharmony_ci        SHARING_LOGD("BufferDispatcher buffer Extended to %{public}d in adaptive capacity calculating.", tmpSize);
1438e0e9324cSopenharmony_ci        SetBufferCapacity(tmpSize);
1439e0e9324cSopenharmony_ci        return;
1440e0e9324cSopenharmony_ci    }
1441e0e9324cSopenharmony_ci
1442e0e9324cSopenharmony_ci    if (keyFrame) {
1443e0e9324cSopenharmony_ci        baseBufferCapacity_ = baseCounter_ + bufferCapacityIncrement_ < maxBufferCapacity_
1444e0e9324cSopenharmony_ci                                  ? baseCounter_ + bufferCapacityIncrement_
1445e0e9324cSopenharmony_ci                                  : maxBufferCapacity_;
1446e0e9324cSopenharmony_ci        if (baseBufferCapacity_ < INITIAL_BUFFER_CAPACITY) {
1447e0e9324cSopenharmony_ci            baseBufferCapacity_ = INITIAL_BUFFER_CAPACITY;
1448e0e9324cSopenharmony_ci        }
1449e0e9324cSopenharmony_ci        doubleBufferCapacity_ = baseBufferCapacity_ * 2 < maxBufferCapacity_ // 2: increasement
1450e0e9324cSopenharmony_ci                                    ? baseBufferCapacity_ * 2                // 2: increasement
1451e0e9324cSopenharmony_ci                                    : maxBufferCapacity_;
1452e0e9324cSopenharmony_ci        gop_ = baseCounter_;
1453e0e9324cSopenharmony_ci        capacityEvaluating_ = gop_ > 0 ? false : true;
1454e0e9324cSopenharmony_ci        SetBufferCapacity(baseBufferCapacity_);
1455e0e9324cSopenharmony_ci        baseCounter_ = 0;
1456e0e9324cSopenharmony_ci        SHARING_LOGI(
1457e0e9324cSopenharmony_ci            "The gop is %{public}d and BufferDispatcher buffer Extended to %{public}d on base capacity confirmed.",
1458e0e9324cSopenharmony_ci            GetCurrentGop(), baseBufferCapacity_);
1459e0e9324cSopenharmony_ci    }
1460e0e9324cSopenharmony_ci}
1461e0e9324cSopenharmony_ci
1462e0e9324cSopenharmony_ciint32_t BufferDispatcher::NotifyThreadWorker(void *userParam)
1463e0e9324cSopenharmony_ci{
1464e0e9324cSopenharmony_ci    SHARING_LOGI("BufferDispatcher DataNotifier thread in.");
1465e0e9324cSopenharmony_ci    RETURN_INVALID_IF_NULL(userParam);
1466e0e9324cSopenharmony_ci    BufferDispatcher *dispatcher = (BufferDispatcher *)userParam;
1467e0e9324cSopenharmony_ci    while (dispatcher->running_) {
1468e0e9324cSopenharmony_ci        std::unique_lock<std::mutex> locker(dispatcher->notifyMutex_);
1469e0e9324cSopenharmony_ci        uint32_t notifyRef = dispatcher->dataBitRef_ & dispatcher->recvBitRef_;
1470e0e9324cSopenharmony_ci        MEDIA_LOGD("DataBitRef %{public}u   recvBitRef_ %{public}d   notifyRef_ %{public}d.",
1471e0e9324cSopenharmony_ci                   dispatcher->dataBitRef_.load(), dispatcher->recvBitRef_.load(), notifyRef);
1472e0e9324cSopenharmony_ci
1473e0e9324cSopenharmony_ci        for (auto &[recvId, notifier] : dispatcher->notifiers_) {
1474e0e9324cSopenharmony_ci            auto index = notifier->GetReadIndex();
1475e0e9324cSopenharmony_ci            if (((RECV_FLAG_BASE << (index * FIX_OFFSET_TWO)) & notifyRef) ||
1476e0e9324cSopenharmony_ci                ((RECV_FLAG_BASE << (index * FIX_OFFSET_TWO + FIX_OFFSET_ONE)) & notifyRef)) {
1477e0e9324cSopenharmony_ci                MediaType notifyType;
1478e0e9324cSopenharmony_ci                if (notifier->IsMixedReceiver()) {
1479e0e9324cSopenharmony_ci                    notifyType = MEDIA_TYPE_AV;
1480e0e9324cSopenharmony_ci                } else {
1481e0e9324cSopenharmony_ci                    notifyType = (((RECV_FLAG_BASE << (index * FIX_OFFSET_TWO)) & notifyRef) ? MEDIA_TYPE_AUDIO
1482e0e9324cSopenharmony_ci                                                                                             : MEDIA_TYPE_VIDEO);
1483e0e9324cSopenharmony_ci                }
1484e0e9324cSopenharmony_ci                MEDIA_LOGD("notify the receiveId: %{public}d, notifyType: %{public}d, notifyRef: %{public}x.", recvId,
1485e0e9324cSopenharmony_ci                           notifyType, notifyRef);
1486e0e9324cSopenharmony_ci                notifier->NotifyDataReceiver(notifyType);
1487e0e9324cSopenharmony_ci            }
1488e0e9324cSopenharmony_ci        }
1489e0e9324cSopenharmony_ci
1490e0e9324cSopenharmony_ci        dispatcher->dataCV_.wait(locker, [&dispatcher]() { return dispatcher->continueNotify_.load(); });
1491e0e9324cSopenharmony_ci        dispatcher->continueNotify_ = false;
1492e0e9324cSopenharmony_ci    }
1493e0e9324cSopenharmony_ci
1494e0e9324cSopenharmony_ci    return 0;
1495e0e9324cSopenharmony_ci}
1496e0e9324cSopenharmony_ci
1497e0e9324cSopenharmony_civoid BufferDispatcher::NotifyReadReady(uint32_t receiverId, MediaType type)
1498e0e9324cSopenharmony_ci{
1499e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1500e0e9324cSopenharmony_ci    auto notifier = GetNotifierByReceiverId(receiverId);
1501e0e9324cSopenharmony_ci    if (notifier == nullptr) {
1502e0e9324cSopenharmony_ci        SHARING_LOGE("notifier is nullptr.");
1503e0e9324cSopenharmony_ci        return;
1504e0e9324cSopenharmony_ci    }
1505e0e9324cSopenharmony_ci
1506e0e9324cSopenharmony_ci    std::shared_lock<std::shared_mutex> lock(bufferMutex_);
1507e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> locker(notifyMutex_);
1508e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AV) {
1509e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, MEDIA_TYPE_VIDEO, true);
1510e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, MEDIA_TYPE_AUDIO, true);
1511e0e9324cSopenharmony_ci    } else {
1512e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, type, true);
1513e0e9324cSopenharmony_ci    }
1514e0e9324cSopenharmony_ci
1515e0e9324cSopenharmony_ci    bool dataAvaliable = notifier->DataAvailable(type);
1516e0e9324cSopenharmony_ci    MEDIA_LOGD("receiverId %{public}d  MediaType %{public}d  dataAvaliable %{public}d.", receiverId, type,
1517e0e9324cSopenharmony_ci               dataAvaliable);
1518e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AV) {
1519e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, MEDIA_TYPE_VIDEO, dataAvaliable);
1520e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, MEDIA_TYPE_AUDIO, dataAvaliable);
1521e0e9324cSopenharmony_ci    } else {
1522e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, type, dataAvaliable);
1523e0e9324cSopenharmony_ci    }
1524e0e9324cSopenharmony_ci
1525e0e9324cSopenharmony_ci    if (!dataAvaliable) {
1526e0e9324cSopenharmony_ci        return;
1527e0e9324cSopenharmony_ci    }
1528e0e9324cSopenharmony_ci
1529e0e9324cSopenharmony_ci    continueNotify_ = true;
1530e0e9324cSopenharmony_ci    dataCV_.notify_one();
1531e0e9324cSopenharmony_ci}
1532e0e9324cSopenharmony_ci
1533e0e9324cSopenharmony_civoid BufferDispatcher::SetDataRef(uint32_t bitref)
1534e0e9324cSopenharmony_ci{
1535e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1536e0e9324cSopenharmony_ci    dataBitRef_ &= bitref;
1537e0e9324cSopenharmony_ci}
1538e0e9324cSopenharmony_ci
1539e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetDataRef()
1540e0e9324cSopenharmony_ci{
1541e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1542e0e9324cSopenharmony_ci    return dataBitRef_;
1543e0e9324cSopenharmony_ci}
1544e0e9324cSopenharmony_ci
1545e0e9324cSopenharmony_civoid BufferDispatcher::SetReadRef(uint32_t bitref)
1546e0e9324cSopenharmony_ci{
1547e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1548e0e9324cSopenharmony_ci    recvBitRef_ &= bitref;
1549e0e9324cSopenharmony_ci}
1550e0e9324cSopenharmony_ci
1551e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetReadRef()
1552e0e9324cSopenharmony_ci{
1553e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1554e0e9324cSopenharmony_ci    return recvBitRef_;
1555e0e9324cSopenharmony_ci}
1556e0e9324cSopenharmony_ci
1557e0e9324cSopenharmony_civoid BufferDispatcher::ActiveDataRef(MediaType type, bool keyFrame)
1558e0e9324cSopenharmony_ci{
1559e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1560e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> locker(notifyMutex_);
1561e0e9324cSopenharmony_ci    uint32_t bitRef = 0x0000;
1562e0e9324cSopenharmony_ci    for (auto &[recvId, notifier] : notifiers_) {
1563e0e9324cSopenharmony_ci        auto index = notifier->GetReadIndex();
1564e0e9324cSopenharmony_ci        if (type == MEDIA_TYPE_AUDIO) {
1565e0e9324cSopenharmony_ci            bitRef |= RECV_FLAG_BASE << (index * 2); // 2: fix offset, get audio notifyer id
1566e0e9324cSopenharmony_ci            continue;
1567e0e9324cSopenharmony_ci        }
1568e0e9324cSopenharmony_ci        bool keyModeReceiver = false;
1569e0e9324cSopenharmony_ci        keyModeReceiver = notifier->IsKeyModeReceiver();
1570e0e9324cSopenharmony_ci        if (keyFrame && keyModeReceiver && keyIndexList_.empty()) {
1571e0e9324cSopenharmony_ci            notifier->videoIndex = circularBuffer_.size() - 1;
1572e0e9324cSopenharmony_ci        }
1573e0e9324cSopenharmony_ci        if ((!keyModeReceiver || (keyModeReceiver && keyFrame))) {
1574e0e9324cSopenharmony_ci            if (index != INVALID_INDEX) {
1575e0e9324cSopenharmony_ci                bitRef |= RECV_FLAG_BASE << (index * 2 + 1); // 2: fix offset, get video notifyer id
1576e0e9324cSopenharmony_ci            }
1577e0e9324cSopenharmony_ci        }
1578e0e9324cSopenharmony_ci    }
1579e0e9324cSopenharmony_ci
1580e0e9324cSopenharmony_ci    dataBitRef_ |= bitRef;
1581e0e9324cSopenharmony_ci}
1582e0e9324cSopenharmony_ci
1583e0e9324cSopenharmony_civoid BufferDispatcher::SetReceiverDataRef(uint32_t receiverId, MediaType type, bool ready)
1584e0e9324cSopenharmony_ci{
1585e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1586e0e9324cSopenharmony_ci    uint32_t index = FindReceiverIndex(receiverId);
1587e0e9324cSopenharmony_ci    if (index == INVALID_INDEX) {
1588e0e9324cSopenharmony_ci        return;
1589e0e9324cSopenharmony_ci    }
1590e0e9324cSopenharmony_ci
1591e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AUDIO) {
1592e0e9324cSopenharmony_ci        uint32_t audioBit = index * 2;
1593e0e9324cSopenharmony_ci        uint32_t bitRef = RECV_FLAG_BASE << audioBit;
1594e0e9324cSopenharmony_ci        MEDIA_LOGD("Audio recvid %{public}d ,bitRef %{public}d ready %{public}d.", receiverId, bitRef, ready);
1595e0e9324cSopenharmony_ci        if (!ready) {
1596e0e9324cSopenharmony_ci            bitRef = ~bitRef;
1597e0e9324cSopenharmony_ci            dataBitRef_ &= bitRef;
1598e0e9324cSopenharmony_ci        } else {
1599e0e9324cSopenharmony_ci            dataBitRef_ |= bitRef;
1600e0e9324cSopenharmony_ci        }
1601e0e9324cSopenharmony_ci    } else if (type == MEDIA_TYPE_VIDEO) {
1602e0e9324cSopenharmony_ci        uint32_t videoBit = index * 2 + 1;
1603e0e9324cSopenharmony_ci        uint32_t bitRef = RECV_FLAG_BASE << videoBit;
1604e0e9324cSopenharmony_ci        MEDIA_LOGD("Video recvid %{public}d ,bitRef %{public}d ready %{public}d.", receiverId, bitRef, ready);
1605e0e9324cSopenharmony_ci        if (!ready) {
1606e0e9324cSopenharmony_ci            bitRef = ~bitRef;
1607e0e9324cSopenharmony_ci            dataBitRef_ &= bitRef;
1608e0e9324cSopenharmony_ci        } else {
1609e0e9324cSopenharmony_ci            dataBitRef_ |= bitRef;
1610e0e9324cSopenharmony_ci        }
1611e0e9324cSopenharmony_ci    }
1612e0e9324cSopenharmony_ci}
1613e0e9324cSopenharmony_ci
1614e0e9324cSopenharmony_civoid BufferDispatcher::SetReceiverReadRef(uint32_t receiverId, MediaType type, bool ready)
1615e0e9324cSopenharmony_ci{
1616e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1617e0e9324cSopenharmony_ci    uint32_t index = FindReceiverIndex(receiverId);
1618e0e9324cSopenharmony_ci    if (index == INVALID_INDEX) {
1619e0e9324cSopenharmony_ci        return;
1620e0e9324cSopenharmony_ci    }
1621e0e9324cSopenharmony_ci
1622e0e9324cSopenharmony_ci    if (type == MEDIA_TYPE_AUDIO) {
1623e0e9324cSopenharmony_ci        uint32_t audioBit = index * 2;
1624e0e9324cSopenharmony_ci        uint32_t bitRef = RECV_FLAG_BASE << audioBit;
1625e0e9324cSopenharmony_ci        MEDIA_LOGD("Audio recvid %{public}d ,bitRef %{public}d ready %{public}d.", receiverId, bitRef, ready);
1626e0e9324cSopenharmony_ci
1627e0e9324cSopenharmony_ci        if (!ready) {
1628e0e9324cSopenharmony_ci            bitRef = ~bitRef;
1629e0e9324cSopenharmony_ci            recvBitRef_ &= bitRef;
1630e0e9324cSopenharmony_ci        } else {
1631e0e9324cSopenharmony_ci            recvBitRef_ |= bitRef;
1632e0e9324cSopenharmony_ci        }
1633e0e9324cSopenharmony_ci    } else if (type == MEDIA_TYPE_VIDEO) {
1634e0e9324cSopenharmony_ci        uint32_t videoBit = index * 2 + 1;
1635e0e9324cSopenharmony_ci        uint32_t bitRef = RECV_FLAG_BASE << videoBit;
1636e0e9324cSopenharmony_ci        MEDIA_LOGD("Video recvid %{public}d ,bitRef %{public}d ready %{public}d.", receiverId, bitRef, ready);
1637e0e9324cSopenharmony_ci
1638e0e9324cSopenharmony_ci        if (!ready) {
1639e0e9324cSopenharmony_ci            bitRef = ~bitRef;
1640e0e9324cSopenharmony_ci            recvBitRef_ &= bitRef;
1641e0e9324cSopenharmony_ci        } else {
1642e0e9324cSopenharmony_ci            recvBitRef_ |= bitRef;
1643e0e9324cSopenharmony_ci        }
1644e0e9324cSopenharmony_ci    }
1645e0e9324cSopenharmony_ci}
1646e0e9324cSopenharmony_ci
1647e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetReceiverDataRef(uint32_t receiverId)
1648e0e9324cSopenharmony_ci{
1649e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1650e0e9324cSopenharmony_ci    return 0;
1651e0e9324cSopenharmony_ci}
1652e0e9324cSopenharmony_ci
1653e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetReceiverReadRef(uint32_t receiverId)
1654e0e9324cSopenharmony_ci{
1655e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1656e0e9324cSopenharmony_ci    uint32_t retBitRef = GetReceiverIndexRef(receiverId);
1657e0e9324cSopenharmony_ci    retBitRef &= recvBitRef_;
1658e0e9324cSopenharmony_ci    return retBitRef;
1659e0e9324cSopenharmony_ci}
1660e0e9324cSopenharmony_ci
1661e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetReceiverIndexRef(uint32_t receiverId)
1662e0e9324cSopenharmony_ci{
1663e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1664e0e9324cSopenharmony_ci    uint32_t index = FindReceiverIndex(receiverId);
1665e0e9324cSopenharmony_ci    uint32_t audioBit = index * 2;
1666e0e9324cSopenharmony_ci    uint32_t videoBit = index * 2 + 1;
1667e0e9324cSopenharmony_ci    uint32_t retBitRef = 0x0000;
1668e0e9324cSopenharmony_ci    retBitRef |= RECV_FLAG_BASE << audioBit;
1669e0e9324cSopenharmony_ci    retBitRef |= RECV_FLAG_BASE << videoBit;
1670e0e9324cSopenharmony_ci    return retBitRef;
1671e0e9324cSopenharmony_ci}
1672e0e9324cSopenharmony_ci
1673e0e9324cSopenharmony_civoid BufferDispatcher::ClearReadBit(uint32_t receiverId, MediaType type)
1674e0e9324cSopenharmony_ci{
1675e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1676e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> indexLocker(notifyMutex_);
1677e0e9324cSopenharmony_ci    if (type != MEDIA_TYPE_AV) {
1678e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, type, false);
1679e0e9324cSopenharmony_ci    } else {
1680e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, MEDIA_TYPE_VIDEO, false);
1681e0e9324cSopenharmony_ci        SetReceiverReadRef(receiverId, MEDIA_TYPE_AUDIO, false);
1682e0e9324cSopenharmony_ci    }
1683e0e9324cSopenharmony_ci}
1684e0e9324cSopenharmony_ci
1685e0e9324cSopenharmony_civoid BufferDispatcher::ClearDataBit(uint32_t receiverId, MediaType type)
1686e0e9324cSopenharmony_ci{
1687e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1688e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> indexLocker(notifyMutex_);
1689e0e9324cSopenharmony_ci    if (type != MEDIA_TYPE_AV) {
1690e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, type, false);
1691e0e9324cSopenharmony_ci    } else {
1692e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, MEDIA_TYPE_VIDEO, false);
1693e0e9324cSopenharmony_ci        SetReceiverDataRef(receiverId, MEDIA_TYPE_AUDIO, false);
1694e0e9324cSopenharmony_ci    }
1695e0e9324cSopenharmony_ci}
1696e0e9324cSopenharmony_ci
1697e0e9324cSopenharmony_cibool BufferDispatcher::IsRead(uint32_t receiverId, uint32_t index)
1698e0e9324cSopenharmony_ci{
1699e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1700e0e9324cSopenharmony_ci    if (index >= circularBuffer_.size()) {
1701e0e9324cSopenharmony_ci        return true;
1702e0e9324cSopenharmony_ci    } else {
1703e0e9324cSopenharmony_ci        return IsDataReaded(receiverId, circularBuffer_.at(index));
1704e0e9324cSopenharmony_ci    }
1705e0e9324cSopenharmony_ci}
1706e0e9324cSopenharmony_ci
1707e0e9324cSopenharmony_civoid BufferDispatcher::ActivateReceiverIndex(uint32_t index, MediaType type)
1708e0e9324cSopenharmony_ci{
1709e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1710e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> lock(notifyMutex_);
1711e0e9324cSopenharmony_ci    for (auto &[recvId, notifier] : notifiers_) {
1712e0e9324cSopenharmony_ci        if (type == MEDIA_TYPE_VIDEO) {
1713e0e9324cSopenharmony_ci            if (notifier->videoIndex == INVALID_INDEX) {
1714e0e9324cSopenharmony_ci                notifier->videoIndex = index;
1715e0e9324cSopenharmony_ci                SHARING_LOGD("RecvId %{public}d Activate %{public}d.", notifier->GetReceiverId(), notifier->videoIndex);
1716e0e9324cSopenharmony_ci                videoNeedActivate_ = false;
1717e0e9324cSopenharmony_ci            }
1718e0e9324cSopenharmony_ci        } else {
1719e0e9324cSopenharmony_ci            if (notifier->audioIndex == INVALID_INDEX) {
1720e0e9324cSopenharmony_ci                notifier->audioIndex = index;
1721e0e9324cSopenharmony_ci                SHARING_LOGD("RecvId %{public}d Activate %{public}d.", notifier->GetReceiverId(), notifier->audioIndex);
1722e0e9324cSopenharmony_ci                audioNeedActivate_ = false;
1723e0e9324cSopenharmony_ci            }
1724e0e9324cSopenharmony_ci        }
1725e0e9324cSopenharmony_ci    }
1726e0e9324cSopenharmony_ci}
1727e0e9324cSopenharmony_civoid BufferDispatcher::UnlockWaitingReceiverIndex(MediaType type)
1728e0e9324cSopenharmony_ci{
1729e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1730e0e9324cSopenharmony_ci}
1731e0e9324cSopenharmony_ci
1732e0e9324cSopenharmony_civoid BufferDispatcher::SetReceiverReadFlag(uint32_t receiverId, DataSpec::Ptr &dataSpec)
1733e0e9324cSopenharmony_ci{
1734e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1735e0e9324cSopenharmony_ci    RETURN_IF_NULL(dataSpec);
1736e0e9324cSopenharmony_ci    uint32_t index = FindReceiverIndex(receiverId);
1737e0e9324cSopenharmony_ci    if (index != INVALID_INDEX) {
1738e0e9324cSopenharmony_ci        dataSpec->reserveFlag |= RECV_FLAG_BASE << index;
1739e0e9324cSopenharmony_ci        MEDIA_LOGD("mediaType: %{public}d, pts: %{public}" PRIu64
1740e0e9324cSopenharmony_ci                   ", reserveFlag: %{public}x, receiverId: %{public}d, index: %{public}d.",
1741e0e9324cSopenharmony_ci                   dataSpec->mediaData->mediaType, dataSpec->mediaData->pts, dataSpec->reserveFlag.load(), receiverId,
1742e0e9324cSopenharmony_ci                   index);
1743e0e9324cSopenharmony_ci    }
1744e0e9324cSopenharmony_ci}
1745e0e9324cSopenharmony_ci
1746e0e9324cSopenharmony_civoid BufferDispatcher::CancelReserve()
1747e0e9324cSopenharmony_ci{
1748e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1749e0e9324cSopenharmony_ci    for (auto &data : circularBuffer_) {
1750e0e9324cSopenharmony_ci        data->reserveFlag = 0xff;
1751e0e9324cSopenharmony_ci    }
1752e0e9324cSopenharmony_ci}
1753e0e9324cSopenharmony_ci
1754e0e9324cSopenharmony_civoid BufferDispatcher::SetSpsNalu(MediaData::Ptr spsbuf)
1755e0e9324cSopenharmony_ci{
1756e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1757e0e9324cSopenharmony_ci    spsBuf_ = spsbuf;
1758e0e9324cSopenharmony_ci}
1759e0e9324cSopenharmony_ci
1760e0e9324cSopenharmony_ciconst MediaData::Ptr BufferDispatcher::GetSPS()
1761e0e9324cSopenharmony_ci{
1762e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1763e0e9324cSopenharmony_ci    return spsBuf_;
1764e0e9324cSopenharmony_ci}
1765e0e9324cSopenharmony_ci
1766e0e9324cSopenharmony_civoid BufferDispatcher::SetPpsNalu(MediaData::Ptr ppsbuf)
1767e0e9324cSopenharmony_ci{
1768e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1769e0e9324cSopenharmony_ci    ppsBuf_ = ppsbuf;
1770e0e9324cSopenharmony_ci}
1771e0e9324cSopenharmony_ci
1772e0e9324cSopenharmony_ciconst MediaData::Ptr BufferDispatcher::GetPPS()
1773e0e9324cSopenharmony_ci{
1774e0e9324cSopenharmony_ci    MEDIA_LOGD("trace.");
1775e0e9324cSopenharmony_ci    return ppsBuf_;
1776e0e9324cSopenharmony_ci}
1777e0e9324cSopenharmony_ci
1778e0e9324cSopenharmony_ciuint32_t BufferDispatcher::GetCurrentGop()
1779e0e9324cSopenharmony_ci{
1780e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1781e0e9324cSopenharmony_ci    return gop_;
1782e0e9324cSopenharmony_ci}
1783e0e9324cSopenharmony_ci
1784e0e9324cSopenharmony_civoid BufferDispatcher::OnKeyRedirect()
1785e0e9324cSopenharmony_ci{
1786e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1787e0e9324cSopenharmony_ci    std::unique_lock<std::mutex> lock(notifyMutex_);
1788e0e9324cSopenharmony_ci    if (keyIndexList_.empty()) {
1789e0e9324cSopenharmony_ci        return;
1790e0e9324cSopenharmony_ci    }
1791e0e9324cSopenharmony_ci
1792e0e9324cSopenharmony_ci    auto nextIndex = keyIndexList_.back();
1793e0e9324cSopenharmony_ci
1794e0e9324cSopenharmony_ci    for (auto &[recvId, notifier] : notifiers_) {
1795e0e9324cSopenharmony_ci        if (notifier->IsKeyRedirectReceiver()) {
1796e0e9324cSopenharmony_ci            SHARING_LOGD("receiverId: %{public}u, videoIndex: %{public}d, nextIndex: %{public}d.",
1797e0e9324cSopenharmony_ci                         notifier->GetReceiverId(), notifier->videoIndex, nextIndex);
1798e0e9324cSopenharmony_ci            auto curIndex = notifier->videoIndex;
1799e0e9324cSopenharmony_ci            notifier->videoIndex = nextIndex;
1800e0e9324cSopenharmony_ci            for (auto i = curIndex; i < nextIndex; i++) {
1801e0e9324cSopenharmony_ci                SetReceiverReadFlag(notifier->GetReceiverId(), circularBuffer_[i]);
1802e0e9324cSopenharmony_ci            }
1803e0e9324cSopenharmony_ci            if (!rapidMode_) {
1804e0e9324cSopenharmony_ci                auto receiver = notifier->GetBufferReceiver();
1805e0e9324cSopenharmony_ci                if (receiver != nullptr) {
1806e0e9324cSopenharmony_ci                    receiver->EnableKeyRedirect(false);
1807e0e9324cSopenharmony_ci                }
1808e0e9324cSopenharmony_ci            }
1809e0e9324cSopenharmony_ci        }
1810e0e9324cSopenharmony_ci    }
1811e0e9324cSopenharmony_ci}
1812e0e9324cSopenharmony_ci
1813e0e9324cSopenharmony_civoid BufferDispatcher::EnableRapidMode(bool enable)
1814e0e9324cSopenharmony_ci{
1815e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
1816e0e9324cSopenharmony_ci    rapidMode_ = enable;
1817e0e9324cSopenharmony_ci}
1818e0e9324cSopenharmony_ci
1819e0e9324cSopenharmony_ci} // namespace Sharing
1820e0e9324cSopenharmony_ci} // namespace OHOS
1821