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 
16 #include "avmuxer_impl.h"
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include "securec.h"
20 #include "avcodec_trace.h"
21 #include "avcodec_log.h"
22 #include "avcodec_errors.h"
23 
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_MUXER, "AVMuxerImpl"};
26 }
27 
28 namespace OHOS {
29 namespace MediaAVCodec {
CreateAVMuxer(int32_t fd,Plugins::OutputFormat format)30 std::shared_ptr<AVMuxer> AVMuxerFactory::CreateAVMuxer(int32_t fd, Plugins::OutputFormat format)
31 {
32     AVCODEC_SYNC_TRACE;
33     CHECK_AND_RETURN_RET_LOG(fd >= 0, nullptr, "fd %{public}d is error!", fd);
34     uint32_t fdPermission = static_cast<uint32_t>(fcntl(fd, F_GETFL, 0));
35     CHECK_AND_RETURN_RET_LOG((fdPermission & O_WRONLY) == O_WRONLY || (fdPermission & O_RDWR) == O_RDWR,
36         nullptr, "No permission to write fd.");
37     CHECK_AND_RETURN_RET_LOG(lseek(fd, 0, SEEK_CUR) != -1, nullptr, "The fd is not seekable");
38 
39     std::shared_ptr<AVMuxerImpl> impl = std::make_shared<AVMuxerImpl>();
40 
41     int32_t ret = impl->Init(fd, format);
42     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init avmuxer implementation failed");
43     return impl;
44 }
45 
AVMuxerImpl()46 AVMuxerImpl::AVMuxerImpl()
47 {
48     AVCODEC_LOGD("AVMuxerImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
49 }
50 
~AVMuxerImpl()51 AVMuxerImpl::~AVMuxerImpl()
52 {
53     AVCODEC_LOGD("AVMuxerImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
54 }
55 
Init(int32_t fd,Plugins::OutputFormat format)56 int32_t AVMuxerImpl::Init(int32_t fd, Plugins::OutputFormat format)
57 {
58     AVCODEC_SYNC_TRACE;
59     muxerEngine_ = std::make_shared<Media::MediaMuxer>(getuid(), getprocpid());
60     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_NO_MEMORY, "Create AVMuxer Engine failed");
61     return StatusConvert(muxerEngine_->Init(fd, format));
62 }
63 
SetParameter(const std::shared_ptr<Meta> & param)64 int32_t AVMuxerImpl::SetParameter(const std::shared_ptr<Meta> &param)
65 {
66     AVCODEC_SYNC_TRACE;
67     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
68     CHECK_AND_RETURN_RET_LOG(param != nullptr, AVCS_ERR_INVALID_VAL, "Invalid parameter");
69     return StatusConvert(muxerEngine_->SetParameter(param));
70 }
71 
SetUserMeta(const std::shared_ptr<Meta> & userMeta)72 int32_t AVMuxerImpl::SetUserMeta(const std::shared_ptr<Meta> &userMeta)
73 {
74     AVCODEC_SYNC_TRACE;
75     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
76     CHECK_AND_RETURN_RET_LOG(userMeta != nullptr, AVCS_ERR_INVALID_VAL, "Invalid parameter");
77     return StatusConvert(muxerEngine_->SetUserMeta(userMeta));
78 }
79 
AddTrack(int32_t & trackIndex,const std::shared_ptr<Meta> & trackDesc)80 int32_t AVMuxerImpl::AddTrack(int32_t &trackIndex, const std::shared_ptr<Meta> &trackDesc)
81 {
82     AVCODEC_SYNC_TRACE;
83     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
84     CHECK_AND_RETURN_RET_LOG(trackDesc != nullptr, AVCS_ERR_INVALID_VAL, "Invalid track format");
85     return StatusConvert(muxerEngine_->AddTrack(trackIndex, trackDesc));
86 }
87 
GetInputBufferQueue(uint32_t trackIndex)88 sptr<AVBufferQueueProducer> AVMuxerImpl::GetInputBufferQueue(uint32_t trackIndex)
89 {
90     AVCODEC_SYNC_TRACE;
91     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, nullptr, "AVMuxer Engine does not exist");
92     return muxerEngine_->GetInputBufferQueue(trackIndex);
93 }
94 
Start()95 int32_t AVMuxerImpl::Start()
96 {
97     AVCODEC_SYNC_TRACE;
98     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
99     return StatusConvert(muxerEngine_->Start());
100 }
101 
WriteSample(uint32_t trackIndex,const std::shared_ptr<AVBuffer> & sample)102 int32_t AVMuxerImpl::WriteSample(uint32_t trackIndex, const std::shared_ptr<AVBuffer> &sample)
103 {
104     AVCODEC_SYNC_TRACE;
105     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
106     CHECK_AND_RETURN_RET_LOG(sample != nullptr && sample->memory_ != nullptr &&
107         sample->memory_->GetSize() >= 0, AVCS_ERR_INVALID_VAL, "Invalid memory");
108     return StatusConvert(muxerEngine_->WriteSample(trackIndex, sample));
109 }
110 
Stop()111 int32_t AVMuxerImpl::Stop()
112 {
113     AVCODEC_SYNC_TRACE;
114     CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
115     return StatusConvert(muxerEngine_->Stop());
116 }
117 
StatusConvert(Media::Status status)118 int32_t AVMuxerImpl::StatusConvert(Media::Status status)
119 {
120     const static std::unordered_map<Media::Status, int32_t> table = {
121         {Status::END_OF_STREAM, AVCodecServiceErrCode::AVCS_ERR_OK},
122         {Status::OK, AVCodecServiceErrCode::AVCS_ERR_OK},
123         {Status::NO_ERROR, AVCodecServiceErrCode::AVCS_ERR_OK},
124         {Status::ERROR_UNKNOWN, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
125         {Status::ERROR_PLUGIN_ALREADY_EXISTS, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
126         {Status::ERROR_INCOMPATIBLE_VERSION, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
127         {Status::ERROR_NO_MEMORY, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY},
128         {Status::ERROR_WRONG_STATE, AVCodecServiceErrCode::AVCS_ERR_INVALID_OPERATION},
129         {Status::ERROR_UNIMPLEMENTED, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT},
130         {Status::ERROR_INVALID_PARAMETER, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
131         {Status::ERROR_INVALID_DATA, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
132         {Status::ERROR_MISMATCHED_TYPE, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
133         {Status::ERROR_TIMED_OUT, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
134         {Status::ERROR_UNSUPPORTED_FORMAT, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT_FILE_TYPE},
135         {Status::ERROR_NOT_ENOUGH_DATA, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
136         {Status::ERROR_NOT_EXISTED, AVCodecServiceErrCode::AVCS_ERR_OPEN_FILE_FAILED},
137         {Status::ERROR_AGAIN, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
138         {Status::ERROR_PERMISSION_DENIED, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
139         {Status::ERROR_NULL_POINTER, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
140         {Status::ERROR_INVALID_OPERATION, AVCodecServiceErrCode::AVCS_ERR_INVALID_OPERATION},
141         {Status::ERROR_CLIENT, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
142         {Status::ERROR_SERVER, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
143         {Status::ERROR_DELAY_READY, AVCodecServiceErrCode::AVCS_ERR_OK},
144         {Status::ERROR_INVALID_BUFFER_SIZE, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
145     };
146     auto ite = table.find(status);
147     if (ite == table.end()) {
148         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
149     }
150     return ite->second;
151 }
152 } // namespace MediaAVCodec
153 } // namespace OHOS