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