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