• 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 "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 }