1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "SampleCallback.h"
17 #include "AVCodecSampleLog.h"
18
19 namespace {
20 constexpr int LIMIT_LOGD_FREQUENCY = 50;
21 constexpr int32_t BYTES_PER_SAMPLE_2 = 2;
22 }
23
24 // Custom write data function
OnRenderWriteData(OH_AudioRenderer * renderer,void * userData,void * buffer,int32_t length)25 int32_t SampleCallback::OnRenderWriteData(OH_AudioRenderer *renderer, void *userData, void *buffer, int32_t length)
26 {
27 (void)renderer;
28 (void)length;
29 CodecUserData *codecUserData = static_cast<CodecUserData *>(userData);
30
31 // Write the data to be played to the buffer by length
32 uint8_t *dest = (uint8_t *)buffer;
33 size_t index = 0;
34 std::unique_lock<std::mutex> lock(codecUserData->outputMutex);
35 // Retrieve the length of the data to be played from the queue
36 while (!codecUserData->renderQueue.empty() && index < length) {
37 dest[index++] = codecUserData->renderQueue.front();
38 codecUserData->renderQueue.pop();
39 }
40
41 AVCODEC_SAMPLE_LOGD("render BufferLength:%{public}d Out buffer count: %{public}u, renderQueue.size: %{public}u, "
42 "renderReadSize: %{public}u", length, codecUserData->outputFrameCount,
43 static_cast<unsigned int>(codecUserData->renderQueue.size()), static_cast<unsigned int>(index));
44
45 codecUserData->frameWrittenForSpeed += length / codecUserData->speed / codecUserData->sampleInfo->
46 audioChannelCount / BYTES_PER_SAMPLE_2;
47 codecUserData->currentPosAudioBufferPts = codecUserData->endPosAudioBufferPts - codecUserData->
48 renderQueue.size() / codecUserData->sampleInfo->audioSampleRate / codecUserData->sampleInfo->
49 audioChannelCount / BYTES_PER_SAMPLE_2;
50
51 if (codecUserData->renderQueue.size() < length) {
52 codecUserData->renderCond.notify_all();
53 }
54 return 0;
55 }
56 // Customize the audio stream event function
OnRenderStreamEvent(OH_AudioRenderer * renderer,void * userData,OH_AudioStream_Event event)57 int32_t SampleCallback::OnRenderStreamEvent(OH_AudioRenderer *renderer, void *userData, OH_AudioStream_Event event)
58 {
59 (void)renderer;
60 (void)userData;
61 (void)event;
62 // Update the player status and interface based on the audio stream event information represented by the event
63 return 0;
64 }
65 // Customize the audio interrupt event function
OnRenderInterruptEvent(OH_AudioRenderer * renderer,void * userData,OH_AudioInterrupt_ForceType type,OH_AudioInterrupt_Hint hint)66 int32_t SampleCallback::OnRenderInterruptEvent(OH_AudioRenderer *renderer, void *userData,
67 OH_AudioInterrupt_ForceType type, OH_AudioInterrupt_Hint hint)
68 {
69 (void)renderer;
70 (void)userData;
71 (void)type;
72 (void)hint;
73 // Update the player status and interface based on the audio interrupt information indicated by type and hint
74 return 0;
75 }
76 // Custom exception callback functions
OnRenderError(OH_AudioRenderer * renderer,void * userData,OH_AudioStream_Result error)77 int32_t SampleCallback::OnRenderError(OH_AudioRenderer *renderer, void *userData, OH_AudioStream_Result error)
78 {
79 (void)renderer;
80 (void)userData;
81 (void)error;
82 AVCODEC_SAMPLE_LOGE("OnRenderError");
83 // Handle the audio exception information based on the error message
84 return 0;
85 }
86
OnCodecError(OH_AVCodec * codec,int32_t errorCode,void * userData)87 void SampleCallback::OnCodecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
88 {
89 (void)codec;
90 (void)errorCode;
91 (void)userData;
92 AVCODEC_SAMPLE_LOGE("On codec error, error code: %{public}d", errorCode);
93 }
94
OnCodecFormatChange(OH_AVCodec * codec,OH_AVFormat * format,void * userData)95 void SampleCallback::OnCodecFormatChange(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
96 {
97 AVCODEC_SAMPLE_LOGI("On codec format change");
98 }
99
OnNeedInputBuffer(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)100 void SampleCallback::OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
101 {
102 if (userData == nullptr) {
103 return;
104 }
105 (void)codec;
106 CodecUserData *codecUserData = static_cast<CodecUserData *>(userData);
107 std::unique_lock<std::mutex> lock(codecUserData->inputMutex);
108 codecUserData->inputBufferInfoQueue.emplace(index, buffer);
109 codecUserData->inputCond.notify_all();
110 }
111
OnNewOutputBuffer(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)112 void SampleCallback::OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
113 {
114 if (userData == nullptr) {
115 return;
116 }
117 (void)codec;
118 CodecUserData *codecUserData = static_cast<CodecUserData *>(userData);
119 std::unique_lock<std::mutex> lock(codecUserData->outputMutex);
120 codecUserData->outputBufferInfoQueue.emplace(index, buffer);
121 codecUserData->outputCond.notify_all();
122 }