• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }