1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "FilePathSinkPlugin"
16 #include "file_path_sink_plugin.h"
17 #include "foundation/log.h"
18 #include "foundation/osal/filesystem/file_system.h"
19 #include "pipeline/filters/common/plugin_utils.h"
20
21 namespace OHOS {
22 namespace Media {
23 namespace Plugin {
24 namespace FileSink {
FilePathSinkPluginCreator(const std::string & name)25 std::shared_ptr<OutputSinkPlugin> FilePathSinkPluginCreator(const std::string& name)
26 {
27 return std::make_shared<FilePathSinkPlugin>(name);
28 }
29
FilePathSinkRegister(const std::shared_ptr<Register> & reg)30 Status FilePathSinkRegister(const std::shared_ptr<Register>& reg)
31 {
32 OutputSinkPluginDef definition;
33 definition.protocolType = ProtocolType::FILE;
34 definition.name = "file_path_sink";
35 definition.description = "file path sink";
36 definition.rank = 100; // 100
37 definition.protocolType = ProtocolType::FILE;
38 definition.creator = FilePathSinkPluginCreator;
39 return reg->AddPlugin(definition);
40 }
41
__anon3d9eb5a70102null42 PLUGIN_DEFINITION(FilePathSink, LicenseType::APACHE_V2, FilePathSinkRegister, [] {});
43
FilePathSinkPlugin(std::string name)44 FilePathSinkPlugin::FilePathSinkPlugin(std::string name)
45 : OutputSinkPlugin(std::move(name)), fp_(nullptr), seekable_(Seekable::SEEKABLE)
46 {
47 }
48
~FilePathSinkPlugin()49 FilePathSinkPlugin::~FilePathSinkPlugin()
50 {
51 if (fp_) {
52 MEDIA_LOG_W("close file in dtor");
53 std::fclose(fp_);
54 fp_ = nullptr;
55 }
56 }
57
Stop()58 Status FilePathSinkPlugin::Stop()
59 {
60 CloseFile();
61 return Status::OK;
62 }
63
SetSink(const MediaSink & sink)64 Status FilePathSinkPlugin::SetSink(const MediaSink& sink)
65 {
66 FALSE_RETURN_V((sink.GetProtocolType() == ProtocolType::FILE && !sink.GetPath().empty()),
67 Status::ERROR_INVALID_DATA);
68 fileName_ = sink.GetPath();
69 return OpenFile();
70 }
71
GetSeekable()72 Seekable FilePathSinkPlugin::GetSeekable()
73 {
74 return seekable_;
75 }
76
SeekTo(uint64_t offset)77 Status FilePathSinkPlugin::SeekTo(uint64_t offset)
78 {
79 FALSE_RETURN_V_MSG_E(fp_ != nullptr, Status::ERROR_WRONG_STATE, "no files have been opened.");
80 if (std::fseek(fp_, offset, SEEK_SET) == 0) {
81 return Status::OK;
82 } else {
83 MEDIA_LOG_W("Seek to " PUBLIC_LOG_U64 " failed due to " PUBLIC_LOG_S, offset, strerror(errno));
84 std::clearerr(fp_);
85 }
86 return Status::ERROR_UNKNOWN;
87 }
88
Write(const std::shared_ptr<Buffer> & buffer)89 Status FilePathSinkPlugin::Write(const std::shared_ptr<Buffer>& buffer)
90 {
91 MEDIA_LOG_DD("Write begin");
92 if (buffer == nullptr || buffer->IsEmpty()) {
93 return Status::OK;
94 }
95 auto bufferData = buffer->GetMemory();
96 std::fwrite(bufferData->GetReadOnlyData(), bufferData->GetSize(), 1, fp_);
97 return Status::OK;
98 }
99
Flush()100 Status FilePathSinkPlugin::Flush()
101 {
102 if (fp_) {
103 MEDIA_LOG_I("flush file");
104 std::fflush(fp_);
105 }
106 return Status::OK;
107 }
108
Reset()109 Status FilePathSinkPlugin::Reset()
110 {
111 return Status::OK;
112 }
OpenFile()113 Status FilePathSinkPlugin::OpenFile()
114 {
115 tmpFileName_ = OSAL::FileSystem::GetTmpFileName();
116 fp_ = std::fopen(tmpFileName_.c_str(), "wb");
117 if (fp_ == nullptr) {
118 int32_t err = errno;
119 MEDIA_LOG_E("Fail to open file due to " PUBLIC_LOG_S, strerror(err));
120 switch (err) {
121 case EPERM:
122 return Status::ERROR_PERMISSION_DENIED;
123 case ENOENT:
124 return Status::ERROR_NOT_EXISTED;
125 default:
126 return Status::ERROR_UNKNOWN;
127 }
128 }
129 MEDIA_LOG_D("open file %s", tmpFileName_.c_str()); // file name is privacy
130 return Status::OK;
131 }
132
CloseFile()133 void FilePathSinkPlugin::CloseFile()
134 {
135 if (fp_) {
136 MEDIA_LOG_D("close file");
137 std::fclose(fp_);
138 fp_ = nullptr;
139 std::rename(tmpFileName_.c_str(), fileName_.c_str());
140 }
141 }
142 } // namespace FileSink
143 } // namespace Plugin
144 } // namespace Media
145 } // namespace OHOS