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 "audio_encoder.h"
17
18 #undef LOG_TAG
19 #define LOG_TAG "AudioEncoder"
20
21 namespace {
22 constexpr int LIMIT_LOGD_FREQUENCY = 50;
23 } // namespace
24
~AudioEncoder()25 AudioEncoder::~AudioEncoder()
26 {
27 Release();
28 }
29
Create(const std::string & codecMime)30 int32_t AudioEncoder::Create(const std::string &codecMime)
31 {
32 encoder_ = OH_AudioCodec_CreateByMime(codecMime.c_str(), true);
33 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Create failed");
34 return AVCODEC_SAMPLE_ERR_OK;
35 }
36
SetCallback(CodecUserData * codecUserData)37 int32_t AudioEncoder::SetCallback(CodecUserData *codecUserData)
38 {
39 int32_t ret = AV_ERR_OK;
40 ret = OH_AudioCodec_RegisterCallback(encoder_,
41 { SampleCallback::OnCodecError, SampleCallback::OnCodecFormatChange,
42 SampleCallback::OnNeedInputBuffer, SampleCallback::OnNewOutputBuffer },
43 codecUserData);
44 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Set callback failed, ret: %{public}d", ret);
45 AVCODEC_SAMPLE_LOGI("====== AudioEncoder SetCallback ======");
46
47 return AVCODEC_SAMPLE_ERR_OK;
48 }
49
Configure(const SampleInfo & sampleInfo)50 int32_t AudioEncoder::Configure(const SampleInfo &sampleInfo)
51 {
52 OH_AVFormat *format = OH_AVFormat_Create();
53 CHECK_AND_RETURN_RET_LOG(format != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "AVFormat create failed");
54
55 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, sampleInfo.audioSampleForamt);
56 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, sampleInfo.audioChannelCount);
57 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleInfo.audioSampleRate);
58 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, sampleInfo.audioBitRate);
59 OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, sampleInfo.audioChannelLayout);
60 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, sampleInfo.audioMaxInputSize);
61 AVCODEC_SAMPLE_LOGI("audioChannelCount:%{public}d audioSampleRate:%{public}d audioBitRate:%{public}d "
62 "audioChannelLayout:%{public}ld",
63 sampleInfo.audioChannelCount, sampleInfo.audioSampleRate, sampleInfo.audioBitRate,
64 sampleInfo.audioChannelLayout);
65
66 int ret = OH_AudioCodec_Configure(encoder_, format);
67 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Config failed, ret: %{public}d", ret);
68 OH_AVFormat_Destroy(format);
69 format = nullptr;
70
71 return AVCODEC_SAMPLE_ERR_OK;
72 }
73
Config(const SampleInfo & sampleInfo,CodecUserData * codecUserData)74 int32_t AudioEncoder::Config(const SampleInfo &sampleInfo, CodecUserData *codecUserData)
75 {
76 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
77 CHECK_AND_RETURN_RET_LOG(codecUserData != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Invalid param: codecUserData");
78
79 // Configure audio encoder
80 int32_t ret = Configure(sampleInfo);
81 CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Configure failed");
82
83 // SetCallback for audio encoder
84 ret = SetCallback(codecUserData);
85 CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR,
86 "Set callback failed, ret: %{public}d", ret);
87
88 // Prepare audio encoder
89 {
90 int ret = OH_AudioCodec_Prepare(encoder_);
91 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Prepare failed, ret: %{public}d", ret);
92 }
93
94 return AVCODEC_SAMPLE_ERR_OK;
95 }
96
Start()97 int32_t AudioEncoder::Start()
98 {
99 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
100
101 int ret = OH_AudioCodec_Start(encoder_);
102 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Start failed, ret: %{public}d", ret);
103 return AVCODEC_SAMPLE_ERR_OK;
104 }
105
PushInputData(CodecBufferInfo & info)106 int32_t AudioEncoder::PushInputData(CodecBufferInfo &info)
107 {
108 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
109 int32_t ret = OH_AVBuffer_SetBufferAttr(reinterpret_cast<OH_AVBuffer *>(info.buffer), &info.attr);
110 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Set avbuffer attr failed");
111 ret = OH_AudioCodec_PushInputBuffer(encoder_, info.bufferIndex);
112 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Push input data failed");
113 return AVCODEC_SAMPLE_ERR_OK;
114 }
115
FreeOutputData(uint32_t bufferIndex)116 int32_t AudioEncoder::FreeOutputData(uint32_t bufferIndex)
117 {
118 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
119
120 int32_t ret = AVCODEC_SAMPLE_ERR_OK;
121 ret = OH_AudioCodec_FreeOutputBuffer(encoder_, bufferIndex);
122 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Free output data failed");
123 return AVCODEC_SAMPLE_ERR_OK;
124 }
125
Stop()126 int32_t AudioEncoder::Stop()
127 {
128 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
129
130 int ret = OH_AudioCodec_Flush(encoder_);
131 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Flush failed, ret: %{public}d", ret);
132
133 ret = OH_AudioCodec_Stop(encoder_);
134 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Stop failed, ret: %{public}d", ret);
135 return AVCODEC_SAMPLE_ERR_OK;
136 }
137
Release()138 int32_t AudioEncoder::Release()
139 {
140 if (encoder_ != nullptr) {
141 OH_AudioCodec_Flush(encoder_);
142 OH_AudioCodec_Stop(encoder_);
143 OH_AudioCodec_Destroy(encoder_);
144 encoder_ = nullptr;
145 }
146 return AVCODEC_SAMPLE_ERR_OK;
147 }