1 /*
2 * Copyright (c) 2023 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 #include "file_source.h"
16
17 #include "securec.h"
18 #include "intell_voice_log.h"
19 #include "memory_guard.h"
20
21 using namespace OHOS::IntellVoiceUtils;
22 #define LOG_TAG "FileSource"
23
24 namespace OHOS {
25 namespace IntellVoiceEngine {
FileSource(uint32_t minBufferSize,uint32_t bufferCnt,const std::string & filePath,std::unique_ptr<FileSourceListener> listener)26 FileSource::FileSource(uint32_t minBufferSize, uint32_t bufferCnt, const std::string &filePath,
27 std::unique_ptr<FileSourceListener> listener)
28 : minBufferSize_(minBufferSize), bufferCnt_(bufferCnt), filePath_(filePath), listener_(std::move(listener))
29 {
30 }
31
~FileSource()32 FileSource::~FileSource()
33 {
34 Stop();
35 }
36
Start()37 bool FileSource::Start()
38 {
39 INTELL_VOICE_LOG_INFO("enter");
40 if (listener_ == nullptr) {
41 INTELL_VOICE_LOG_ERROR("listener_ is nullptr");
42 return false;
43 }
44
45 if (minBufferSize_ == 0) {
46 INTELL_VOICE_LOG_ERROR("minBufferSize_ is invalid");
47 return false;
48 }
49
50 buffer_ = std::shared_ptr<uint8_t>(new uint8_t[minBufferSize_], [](uint8_t *p) { delete[] p; });
51 if (buffer_ == nullptr) {
52 INTELL_VOICE_LOG_ERROR("malloc buffer failed");
53 return false;
54 }
55
56 fileIn_ = std::make_unique<std::ifstream>(filePath_, std::ios::binary);
57 if (fileIn_ == nullptr) {
58 INTELL_VOICE_LOG_ERROR("open input file failed");
59 return false;
60 }
61
62 fileIn_->seekg(0, fileIn_->end);
63 uint32_t size = static_cast<uint32_t>(fileIn_->tellg());
64 if (size < minBufferSize_ * bufferCnt_) {
65 INTELL_VOICE_LOG_ERROR("file size:%{public}u is smaller than required", size);
66 fileIn_->close();
67 fileIn_ = nullptr;
68 return false;
69 }
70
71 isReading_.store(true);
72 std::thread t1(std::bind(&FileSource::ReadThread, this));
73 readThread_ = std::move(t1);
74 return true;
75 }
76
ReadThread()77 void FileSource::ReadThread()
78 {
79 uint32_t readCnt = 0;
80 bool isError = true;
81 if (fileIn_ == nullptr) {
82 INTELL_VOICE_LOG_ERROR("fileIn_ is nullptr");
83 return;
84 }
85
86 fileIn_->seekg(0, fileIn_->beg);
87
88 while (isReading_.load()) {
89 if (readCnt >= bufferCnt_) {
90 INTELL_VOICE_LOG_INFO("finish reading data");
91 isError = false;
92 break;
93 }
94
95 if (!(fileIn_->read(reinterpret_cast<char *>(buffer_.get()), minBufferSize_))) {
96 INTELL_VOICE_LOG_ERROR("failed to read file");
97 break;
98 }
99
100 if (listener_ != nullptr) {
101 listener_->fileBufferCb_(buffer_.get(), minBufferSize_);
102 }
103
104 ++readCnt;
105 }
106
107 if (listener_ != nullptr) {
108 listener_->fileEndCb_(isError);
109 }
110 }
111
Stop()112 void FileSource::Stop()
113 {
114 INTELL_VOICE_LOG_INFO("enter");
115 MemoryGuard memoryGuard;
116 if (isReading_.load()) {
117 isReading_.store(false);
118 readThread_.join();
119 }
120
121 if (fileIn_ != nullptr) {
122 fileIn_->close();
123 fileIn_ = nullptr;
124 }
125
126 buffer_ = nullptr;
127 listener_ = nullptr;
128 }
129 }
130 }