1 /*
2 * Copyright (c) 2024 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 "media_audio_encoder.h"
17 #include <filesystem>
18 #include <sstream>
19 #include <map>
20 #include <sys/stat.h>
21 #include "log.h"
22 #include "securec.h"
23 #include "monitor_error.h"
24 #include "monitor_utils.h"
25 #include "string_converter.h"
26
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FOUNDATION, "HiStreamer"};
29 }
30
31 namespace OHOS {
32 namespace Media {
33 namespace MediaMonitor {
34
35 const int MAX_AUDIO_ARGS = 3;
36 const int ARGS_SAMPLERATE_POS = 3;
37 const int ARGS_CHANNEL_POS = 2;
38 const int ARGS_SAMPLEFORMAT_POS = 1;
39 const uint32_t DEFAULT_SAMPLERATE = 48000;
40 const uint32_t DEFAULT_CHANNELS = 1;
41
42 const int S24LE_SAMPLESIZE = 3;
43 const int S24LE_BYTE_SHIFT_8 = 8;
44 const int S24LE_BYTE_SHIFT_16 = 16;
45 const int S24LE_BYTE_SHIFT_24 = 24;
46 const int S24LE_BYTE_INDEX_0 = 0;
47 const int S24LE_BYTE_INDEX_1 = 1;
48 const int S24LE_BYTE_INDEX_2 = 2;
49
50 const mode_t MODE = 0775;
51 const std::string PCM_FILE = ".pcm";
52 const std::string FLAC_FILE = ".flac";
53 const std::string BLUETOOTCH_FILE = "bluetooth";
54 const uint8_t BLUETOOTH_SAMPLE_FORMAT_OFFSET = 1;
55 // samples(flac: 4608) * formatSize(f32: 4) * channles(6)
56 constexpr size_t MAX_BUFFER_LEN = 4608 * 4 * 6;
57 // samples(flac: 4608) * formatSize(s16: 2) * channles(2)
58 constexpr size_t DEFALUT_BUFFER_LEN = 4608 * 2 * 2;
59
60 static std::map<SampleFormat, AVSampleFormat> AudioSampleMap = {
61 {SampleFormat::U8, AV_SAMPLE_FMT_U8},
62 {SampleFormat::S16LE, AV_SAMPLE_FMT_S16},
63 {SampleFormat::S24LE, AV_SAMPLE_FMT_S32},
64 {SampleFormat::S32LE, AV_SAMPLE_FMT_S32},
65 {SampleFormat::F32LE, AV_SAMPLE_FMT_FLT}
66 };
67 // encoder support sample rate
68 const std::vector<std::string> SupportedSampleRates = {
69 "8000", "11025", "12000", "16000", "22050", "24000", "32000",
70 "44100", "48000", "64000", "88200", "96000", "192000"
71 };
72 // encoder support audio channels
73 const std::vector<std::string> SupportedChannels = {"1", "2", "3", "4", "5", "6"};
74 // encoder support sample format 1 S16le, 2 S24le, 3 S32le, 4 F32le
75 const std::vector<std::string> SupportedSampleFormats = {"1", "2", "3", "4"};
76
SampleConvert(std::shared_ptr<FFmpegApiWrap> apiWrap)77 SampleConvert::SampleConvert(std::shared_ptr<FFmpegApiWrap> apiWrap)
78 : apiWrap_(apiWrap)
79 {
80 }
81
~SampleConvert()82 SampleConvert::~SampleConvert()
83 {
84 Release();
85 }
86
Init(const ResamplePara & param)87 int32_t SampleConvert::Init(const ResamplePara ¶m)
88 {
89 resamplePara_ = param;
90 if (apiWrap_ == nullptr) {
91 MEDIA_LOG_E("api load failed");
92 return ERROR;
93 }
94 auto swrContext = apiWrap_->SwrAlloc();
95 if (swrContext == nullptr) {
96 MEDIA_LOG_E("cannot allocate swr context");
97 return ERROR;
98 }
99 swrContext = apiWrap_->SwrSetOpts(swrContext,
100 resamplePara_.channelLayout, resamplePara_.destFmt, resamplePara_.sampleRate,
101 resamplePara_.channelLayout, resamplePara_.srcFfFmt, resamplePara_.sampleRate,
102 0, nullptr);
103 if (apiWrap_->SwrInit(swrContext) != 0) {
104 MEDIA_LOG_E("swr init error");
105 return ERROR;
106 }
107 swrCtx_ = std::shared_ptr<SwrContext>(swrContext, [this](SwrContext* ptr) {
108 apiWrap_->SwrFree(&ptr);
109 });
110 isInit_ = true;
111 return SUCCESS;
112 }
113
Convert(const uint8_t * src,size_t size,AVFrame * dstFrame)114 int32_t SampleConvert::Convert(const uint8_t *src, size_t size, AVFrame *dstFrame)
115 {
116 FALSE_RETURN_V_MSG_E(isInit_ == true, ERROR, "init error convert failed");
117 FALSE_RETURN_V_MSG_E(dstFrame != nullptr, ERROR, "dst frame is nullptr");
118 size_t lineSize = size / resamplePara_.channels;
119 std::vector<const uint8_t*> tmpInput(resamplePara_.channels);
120 tmpInput[0] = src;
121 if (apiWrap_->SampleFmtIsPlannar(resamplePara_.srcFfFmt)) {
122 for (size_t i = 1; i < tmpInput.size(); ++i) {
123 tmpInput[i] = tmpInput[i-1] + lineSize;
124 }
125 }
126 auto res = apiWrap_->SwrConvert(swrCtx_.get(),
127 dstFrame->extended_data, dstFrame->nb_samples,
128 tmpInput.data(), dstFrame->nb_samples);
129 if (res < 0) {
130 MEDIA_LOG_E("resample input failed");
131 return ERROR;
132 }
133 return SUCCESS;
134 }
135
Release()136 void SampleConvert::Release()
137 {
138 swrCtx_ = nullptr;
139 isInit_ = false;
140 }
141
EncodePcmFiles(const std::string & fileDir)142 int32_t MediaAudioEncoder::EncodePcmFiles(const std::string &fileDir)
143 {
144 int32_t status = SUCCESS;
145 apiWrap_ = std::make_shared<FFmpegApiWrap>();
146 if (!apiWrap_->Open()) {
147 apiWrap_->Close();
148 MEDIA_LOG_E("load encoder api failed");
149 apiWrap_ = nullptr;
150 return ERROR;
151 }
152
153 std::error_code errorCode;
154 std::filesystem::directory_iterator iter(fileDir, errorCode);
155 if (errorCode) {
156 MEDIA_LOG_E("get file failed");
157 return ERROR;
158 }
159 for (const auto &elem : iter) {
160 if (std::filesystem::is_regular_file(elem.status())) {
161 if (elem.path().extension() != PCM_FILE) {
162 continue;
163 }
164 std::string in = elem.path();
165 status = EncodePcmToFlac(in);
166 if (status == SUCCESS) {
167 DeleteSrcFile(in);
168 }
169 }
170 }
171
172 apiWrap_->Close();
173 apiWrap_ = nullptr;
174 return SUCCESS;
175 }
176
EncodePcmToFlac(const std::string & in)177 int32_t MediaAudioEncoder::EncodePcmToFlac(const std::string &in)
178 {
179 int32_t status = SUCCESS;
180 FALSE_RETURN_V_MSG_E(IsRealPath(in), ERROR, "check path failed");
181 status = Init(in);
182 if (status != SUCCESS) {
183 Release();
184 return ERROR;
185 }
186 size_t bufferLen = PcmDataSize();
187 if (bufferLen <= 0 || bufferLen > MAX_BUFFER_LEN) {
188 Release();
189 return ERROR;
190 }
191 uint8_t *buffer = reinterpret_cast<uint8_t *>(malloc(bufferLen));
192 if (buffer == nullptr) {
193 Release();
194 return ERROR;
195 }
196 FILE *pcmFile = fopen(in.c_str(), "rb");
197 if (pcmFile == nullptr) {
198 free(buffer);
199 Release();
200 return ERROR;
201 }
202 while (!feof(pcmFile)) {
203 errno_t err = memset_s(static_cast<void *>(buffer), bufferLen, 0, bufferLen);
204 if (err != EOK) {
205 status = ERROR;
206 break;
207 }
208 size_t bytesToWrite = fread(buffer, 1, bufferLen, pcmFile);
209 if (bytesToWrite <= 0) {
210 status = ERROR;
211 break;
212 }
213 status = WritePcm(buffer, bufferLen);
214 if (status != SUCCESS) {
215 break;
216 }
217 }
218 (void)fclose(pcmFile);
219 free(buffer);
220 Release();
221 return status;
222 }
223
Init(const std::string & inputFile)224 int32_t MediaAudioEncoder::Init(const std::string &inputFile)
225 {
226 FALSE_RETURN_V_MSG_E(apiWrap_ != nullptr, ERROR, "load wrap api failed");
227 int32_t ret = SUCCESS;
228 AudioEncodeConfig config;
229 ret = GetAudioConfig(inputFile, config);
230 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "get audio config failed");
231 ret = InitAudioEncode(config);
232 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "init encoder failed");
233 ret = InitMux();
234 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "init muxer failed");
235 ret = InitFrame();
236 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "init frame failed");
237 ret = InitPacket();
238 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "init packet failed");
239 ret = InitSampleConvert();
240 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ret, "init convert failed");
241 isInit_ = true;
242 return ret;
243 }
244
IsSupportAudioArgs(std::string & audioArg,const std::vector<std::string> & supportList)245 bool MediaAudioEncoder::IsSupportAudioArgs(std::string &audioArg, const std::vector<std::string> &supportList)
246 {
247 for (auto &arg : supportList) {
248 if (audioArg == arg) {
249 return true;
250 }
251 }
252 return false;
253 }
254
ParseAudioArgs(const std::string & fileName,AudioEncodeConfig & config)255 int32_t MediaAudioEncoder::ParseAudioArgs(const std::string &fileName, AudioEncodeConfig &config)
256 {
257 std::string sampleRate;
258 std::string channel;
259 std::string sampleFormat;
260
261 std::vector<std::string> res;
262 std::string nameStr = fileName.substr(0, fileName.rfind("."));
263 std::istringstream iss(nameStr);
264 std::string str;
265 while (std::getline(iss, str, '_')) {
266 res.push_back(str);
267 }
268 FALSE_RETURN_V_MSG_E(res.size() >= MAX_AUDIO_ARGS, ERROR,
269 "parse args error, %{public}s", fileName.c_str());
270 // xxx_sampleRate_channel_sampleFormat.flac
271 sampleRate = res[res.size() - ARGS_SAMPLERATE_POS];
272 channel = res[res.size() - ARGS_CHANNEL_POS];
273 sampleFormat = res[res.size() - ARGS_SAMPLEFORMAT_POS];
274 if (IsSupportAudioArgs(sampleRate, SupportedSampleRates) &&
275 IsSupportAudioArgs(channel, SupportedChannels) &&
276 IsSupportAudioArgs(sampleFormat, SupportedSampleFormats)) {
277 FALSE_RETURN_V_MSG_E(StringConverter(sampleRate, config.sampleRate), ERROR,
278 "parse sampleRate error, %{public}s", sampleRate.c_str());
279 FALSE_RETURN_V_MSG_E(StringConverter(channel, config.channels), ERROR,
280 "parse channel error, %{public}s", channel.c_str());
281 uint8_t sampleFormatValue = 0;
282 FALSE_RETURN_V_MSG_E(StringConverter(sampleFormat, sampleFormatValue), ERROR,
283 "parse sampleFormat error, %{public}s", sampleFormat.c_str());
284 config.sampleFmt = static_cast<SampleFormat>(sampleFormatValue);
285 MEDIA_LOG_I("parser success %{public}s %{public}s %{public}s",
286 sampleRate.c_str(), channel.c_str(), sampleFormat.c_str());
287 } else {
288 MEDIA_LOG_I("parser error filename: %{public}s", fileName.c_str());
289 return ERROR;
290 }
291 if (fileName.find(BLUETOOTCH_FILE) != std::string::npos) {
292 uint8_t sampleFormatValue = 0;
293 FALSE_RETURN_V_MSG_E(StringConverter(sampleFormat, sampleFormatValue), ERROR,
294 "parse sampleFormat error, %{public}s", sampleFormat.c_str());
295 config.sampleFmt = static_cast<SampleFormat>(sampleFormatValue - BLUETOOTH_SAMPLE_FORMAT_OFFSET);
296 }
297 return SUCCESS;
298 }
299
GetAudioConfig(const std::string & inFullName,AudioEncodeConfig & config)300 int32_t MediaAudioEncoder::GetAudioConfig(const std::string &inFullName, AudioEncodeConfig &config)
301 {
302 fileName_ = inFullName.substr(0, inFullName.length() - PCM_FILE.length()) + FLAC_FILE;
303 std::string filename = std::filesystem::path(fileName_).filename().string();
304 config.bitRate = 0;
305 config.sampleRate = DEFAULT_SAMPLERATE;
306 config.channels = DEFAULT_CHANNELS;
307 config.sampleFmt = S16LE;
308 config.audioCodecId = AV_CODEC_ID_FLAC;
309 int32_t ret = ParseAudioArgs(filename, config);
310 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ERROR, "parse args error");
311 srcSampleFormat_ = config.sampleFmt;
312 return ret;
313 }
314
InitMux()315 int32_t MediaAudioEncoder::InitMux()
316 {
317 int32_t ret = SUCCESS;
318 AVFormatContext *formatCtx = nullptr;
319 ret = apiWrap_->FormatAllocOutputContext(&formatCtx, nullptr, nullptr, fileName_.c_str());
320 if (formatCtx == nullptr) {
321 MEDIA_LOG_E("could not deduce output format from file extension %{public}s", fileName_.c_str());
322 return ERROR;
323 }
324 formatContext_ = std::shared_ptr<AVFormatContext>(formatCtx, [this](AVFormatContext* ptr) {
325 apiWrap_->FormatFreeContext(ptr);
326 });
327 if (audioCodecContext_ != nullptr) {
328 AVStream *audioStream = nullptr;
329 audioStream = apiWrap_->FormatNewStream(formatContext_.get(), nullptr);
330 FALSE_RETURN_V_MSG_E(audioStream != nullptr, ERROR, "new audio stream error");
331 ret = apiWrap_->CodecParamFromContext(audioStream->codecpar, audioCodecContext_.get());
332 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "could not copy the stream parameters");
333 audioStream->codecpar->codec_tag = 0;
334 }
335 if (videoCodecContext_ != nullptr) {
336 AVStream *videoStream = nullptr;
337 videoStream = apiWrap_->FormatNewStream(formatContext_.get(), nullptr);
338 FALSE_RETURN_V_MSG_E(videoStream != nullptr, ERROR, "new video stream error");
339 ret = apiWrap_->CodecParamFromContext(videoStream->codecpar, videoCodecContext_.get());
340 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "could not copy the stream parameters");
341 videoStream->codecpar->codec_tag = 0;
342 }
343 unsigned int formatCtxFlag = static_cast<unsigned int>(formatContext_->oformat->flags);
344 if (!(formatCtxFlag & AVFMT_NOFILE)) {
345 ret = apiWrap_->IoOpen(&formatContext_->pb, fileName_.c_str(), AVIO_FLAG_WRITE,
346 &formatContext_->interrupt_callback, nullptr);
347 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "open fail %{public}s", fileName_.c_str());
348 }
349 ret = apiWrap_->FormatWriteHeader(formatContext_.get(), nullptr);
350 if (ret < 0) {
351 MEDIA_LOG_E("error occurred when write header: %{public}d", ret);
352 return ERROR;
353 }
354 return SUCCESS;
355 }
356
InitAudioEncode(const AudioEncodeConfig & audioConfig)357 int32_t MediaAudioEncoder::InitAudioEncode(const AudioEncodeConfig &audioConfig)
358 {
359 int32_t ret = SUCCESS;
360 const AVCodec *codec = nullptr;
361 codec = apiWrap_->CodecFindEncoder(audioConfig.audioCodecId);
362 FALSE_RETURN_V_MSG_E(codec != nullptr, ERROR, "find audio codec failed");
363 AVCodecContext *context = nullptr;
364 context = apiWrap_->CodecAllocContext(codec);
365 FALSE_RETURN_V_MSG_E(context != nullptr, ERROR, "alloc audio encode context failed");
366
367 audioCodecContext_ = std::shared_ptr<AVCodecContext>(context, [this](AVCodecContext* ptr) {
368 apiWrap_->CodecFreeContext(&ptr);
369 });
370
371 audioCodecContext_->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
372 if (srcSampleFormat_ > SampleFormat::S16LE && audioConfig.audioCodecId == AV_CODEC_ID_FLAC) {
373 audioCodecContext_->sample_fmt = AV_SAMPLE_FMT_S32;
374 }
375 audioCodecContext_->bit_rate = audioConfig.bitRate;
376 audioCodecContext_->sample_rate = audioConfig.sampleRate;
377 audioCodecContext_->channels = audioConfig.channels;
378 audioCodecContext_->channel_layout = static_cast<uint64_t>(apiWrap_->GetChannelLayout(audioConfig.channels));
379
380 unsigned int codecCtxFlag = static_cast<unsigned int>(audioCodecContext_->flags);
381 codecCtxFlag |= AV_CODEC_FLAG_GLOBAL_HEADER;
382 audioCodecContext_->flags = static_cast<int>(codecCtxFlag);
383 ret = apiWrap_->CodecOpen(audioCodecContext_.get(), codec, nullptr);
384 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "could not open audio codec %{public}d", ret);
385 return SUCCESS;
386 }
387
InitFrame()388 int32_t MediaAudioEncoder::InitFrame()
389 {
390 AVFrame* frame = apiWrap_->FrameAlloc();
391 FALSE_RETURN_V_MSG_E(frame != nullptr, ERROR, "alloc frame failed");
392 avFrame_ = std::shared_ptr<AVFrame>(frame, [this](AVFrame* frame) {
393 apiWrap_->FrameFree(&frame);
394 });
395
396 avFrame_->format = audioCodecContext_->sample_fmt;
397 avFrame_->nb_samples = audioCodecContext_->frame_size;
398 avFrame_->channel_layout = audioCodecContext_->channel_layout;
399 avFrame_->sample_rate = audioCodecContext_->sample_rate;
400 avFrame_->channels = audioCodecContext_->channels;
401 int32_t ret = apiWrap_->FrameGetBuffer(avFrame_.get(), 0);
402 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "get frame buffer failed %{public}d", ret);
403 return SUCCESS;
404 }
405
InitPacket()406 int32_t MediaAudioEncoder::InitPacket()
407 {
408 AVPacket *packet = apiWrap_->PacketAlloc();
409 FALSE_RETURN_V_MSG_E(packet != nullptr, ERROR, "alloc packet failed");
410 avPacket_ = std::shared_ptr<AVPacket>(packet, [this](AVPacket *packet) {
411 apiWrap_->PacketFree(&packet);
412 });
413 return SUCCESS;
414 }
415
InitSampleConvert()416 int32_t MediaAudioEncoder::InitSampleConvert()
417 {
418 FALSE_RETURN_V_MSG_E(avFrame_ != nullptr, ERROR, "frame error.");
419 if (srcSampleFormat_ > SampleFormat::U8 && srcSampleFormat_ < SampleFormat::F32LE) {
420 MEDIA_LOG_I("in sample format no need convert %{public}d", srcSampleFormat_);
421 sampleConvert_ = nullptr;
422 return SUCCESS;
423 }
424
425 sampleConvert_ = std::make_shared<SampleConvert>(apiWrap_);
426 ResamplePara param {
427 avFrame_->channels,
428 avFrame_->sample_rate,
429 avFrame_->channel_layout,
430 AudioSampleMap[srcSampleFormat_],
431 (AVSampleFormat)avFrame_->format,
432 };
433 int32_t ret = sampleConvert_->Init(param);
434 return ret;
435 }
436
CopyS24ToS32(int32_t * dst,const uint8_t * src,size_t count)437 void MediaAudioEncoder::CopyS24ToS32(int32_t *dst, const uint8_t *src, size_t count)
438 {
439 if (dst == nullptr || src == nullptr) {
440 return;
441 }
442
443 dst += count;
444 src += count * S24LE_SAMPLESIZE;
445 for (; count > 0; --count) {
446 src -= S24LE_SAMPLESIZE;
447 *--dst = (int32_t)((src[S24LE_BYTE_INDEX_0] << S24LE_BYTE_SHIFT_8) |
448 (src[S24LE_BYTE_INDEX_1] << S24LE_BYTE_SHIFT_16) |
449 (src[S24LE_BYTE_INDEX_2] << S24LE_BYTE_SHIFT_24));
450 }
451 }
452
FillFrameFromBuffer(const uint8_t * buffer,size_t size)453 int32_t MediaAudioEncoder::FillFrameFromBuffer(const uint8_t *buffer, size_t size)
454 {
455 FALSE_RETURN_V_MSG_E(avFrame_->linesize[0] >= static_cast<int>(size), ERROR, "frame size error");
456 if (srcSampleFormat_ == SampleFormat::S24LE) {
457 size_t count = size / S24LE_SAMPLESIZE;
458 CopyS24ToS32(reinterpret_cast<int32_t*>(avFrame_->data[0]), buffer, count);
459 } else {
460 errno_t err = memcpy_s(avFrame_->data[0], avFrame_->linesize[0], buffer, size);
461 FALSE_RETURN_V_MSG_E(err == EOK, ERROR, "memcpy error");
462 }
463 return SUCCESS;
464 }
465
WritePcm(const uint8_t * buffer,size_t size)466 int32_t MediaAudioEncoder::WritePcm(const uint8_t *buffer, size_t size)
467 {
468 int32_t ret = SUCCESS;
469 FALSE_RETURN_V_MSG_E(isInit_ == true, ERROR, "init error");
470 FALSE_RETURN_V_MSG_E(buffer != nullptr, ERROR, "buffer nullptr");
471 FALSE_RETURN_V_MSG_E(avFrame_ != nullptr, ERROR, "frame nullptr");
472 if (sampleConvert_ != nullptr) {
473 ret = sampleConvert_->Convert(buffer, size, avFrame_.get());
474 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ERROR, "resample frame error");
475 } else {
476 ret = FillFrameFromBuffer(buffer, size);
477 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ERROR, "fill frame error");
478 }
479 ret = WriteFrame();
480 return ret;
481 }
482
WriteFrame()483 int32_t MediaAudioEncoder::WriteFrame()
484 {
485 int32_t ret = SUCCESS;
486 FALSE_RETURN_V_MSG_E(avFrame_ != nullptr, ERROR, "frame nullptr");
487 FALSE_RETURN_V_MSG_E(avPacket_ != nullptr, ERROR, "packet nullptr");
488 ret = apiWrap_->CodecSendFrame(audioCodecContext_.get(), avFrame_.get());
489 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "send frame failed %{public}d", ret);
490 while (true) {
491 ret = apiWrap_->CodecRecvPacket(audioCodecContext_.get(), avPacket_.get());
492 if (ret == 0) {
493 ret = apiWrap_->FormatWriteFrame(formatContext_.get(), avPacket_.get());
494 apiWrap_->PacketUnref(avPacket_.get());
495 FALSE_RETURN_V_MSG_E(ret >= 0, ERROR, "write packet error");
496 continue;
497 } else if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF)) {
498 ret = SUCCESS;
499 } else {
500 MEDIA_LOG_E("receive packet error");
501 }
502 break;
503 }
504 FALSE_RETURN_V_MSG_E(ret == SUCCESS, ERROR, "write packet error");
505 return SUCCESS;
506 }
507
ResetEncoderCtx()508 void MediaAudioEncoder::ResetEncoderCtx()
509 {
510 avPacket_ = nullptr;
511 avFrame_ = nullptr;
512 audioCodecContext_ = nullptr;
513 videoCodecContext_ = nullptr;
514 formatContext_ = nullptr;
515 sampleConvert_ = nullptr;
516 }
517
Release()518 void MediaAudioEncoder::Release()
519 {
520 FALSE_RETURN_MSG(apiWrap_ != nullptr, "load api error");
521 if (formatContext_ == nullptr) {
522 ResetEncoderCtx();
523 isInit_ = false;
524 return;
525 }
526 if (isInit_) {
527 apiWrap_->FormatWriteTrailer(formatContext_.get());
528 apiWrap_->IoFlush(formatContext_->pb);
529 unsigned int formatCtxFlag = static_cast<unsigned int>(formatContext_->oformat->flags);
530 if (!(formatCtxFlag & AVFMT_NOFILE)) {
531 (void)apiWrap_->IoClose(formatContext_->pb);
532 formatContext_->pb = nullptr;
533 }
534 (void)apiWrap_->FormatFlush(formatContext_.get());
535 }
536 ResetEncoderCtx();
537 isInit_ = false;
538 return;
539 }
540
PcmDataSize()541 size_t MediaAudioEncoder::PcmDataSize()
542 {
543 size_t size = DEFALUT_BUFFER_LEN;
544 if (audioCodecContext_ == nullptr) {
545 return size;
546 }
547
548 int bytesPerSample = 0;
549 if (srcSampleFormat_ == SampleFormat::S24LE) {
550 bytesPerSample = S24LE_SAMPLESIZE;
551 } else {
552 bytesPerSample = apiWrap_->GetBytesPerSample(AudioSampleMap[srcSampleFormat_]);
553 }
554
555 size = static_cast<size_t>(audioCodecContext_->frame_size
556 * audioCodecContext_->channels
557 * bytesPerSample);
558 return size;
559 }
560
DeleteSrcFile(const std::string & filePath)561 bool MediaAudioEncoder::DeleteSrcFile(const std::string &filePath)
562 {
563 if (!IsRealPath(filePath)) {
564 return false;
565 }
566 (void)chmod(filePath.c_str(), MODE);
567 if (remove(filePath.c_str()) != 0) {
568 MEDIA_LOG_E("remove file %{public}s failed ", filePath.c_str());
569 return false;
570 }
571 return true;
572 }
573 } // namespace MediaMonitor
574 } // namespace Media
575 } // namespace OHOS