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 <vector> 16#include <unistd.h> 17#include <fcntl.h> 18#include "i_avcodec_service.h" 19#include "avcodec_errors.h" 20#include "avcodec_log.h" 21#include "avcodec_trace.h" 22#include "avsource_impl.h" 23#include "common/media_source.h" 24#include "common/status.h" 25 26namespace { 27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_DEMUXER, "AVSourceImpl"}; 28} 29 30namespace OHOS { 31namespace MediaAVCodec { 32using namespace Media; 33using namespace Media::Plugins; 34std::shared_ptr<AVSource> AVSourceFactory::CreateWithURI(const std::string &uri) 35{ 36 AVCODEC_SYNC_TRACE; 37 38 AVCODEC_LOGD("Create source with uri %{private}s", uri.c_str()); 39 40 std::shared_ptr<AVSourceImpl> sourceImpl = std::make_shared<AVSourceImpl>(); 41 CHECK_AND_RETURN_RET_LOG(sourceImpl != nullptr, nullptr, "New avsource failed"); 42 43 int32_t ret = sourceImpl->InitWithURI(uri); 44 45 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init avsource failed"); 46 47 return sourceImpl; 48} 49 50std::shared_ptr<AVSource> AVSourceFactory::CreateWithFD(int32_t fd, int64_t offset, int64_t size) 51{ 52 AVCODEC_SYNC_TRACE; 53 54 AVCODEC_LOGD("Create source with fd %{private}d, offset=%{public}" PRId64 ", size=%{public}" PRId64, 55 fd, offset, size); 56 57 std::shared_ptr<AVSourceImpl> sourceImpl = std::make_shared<AVSourceImpl>(); 58 CHECK_AND_RETURN_RET_LOG(sourceImpl != nullptr, nullptr, "New avsource failed"); 59 60 int32_t ret = sourceImpl->InitWithFD(fd, offset, size); 61 62 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init avsource failed"); 63 64 return sourceImpl; 65} 66 67std::shared_ptr<AVSource> AVSourceFactory::CreateWithDataSource( 68 const std::shared_ptr<Media::IMediaDataSource> &dataSource) 69{ 70 AVCODEC_SYNC_TRACE; 71 72 std::shared_ptr<AVSourceImpl> sourceImpl = std::make_shared<AVSourceImpl>(); 73 CHECK_AND_RETURN_RET_LOG(sourceImpl != nullptr, nullptr, "New avsource failed"); 74 75 int32_t ret = sourceImpl->InitWithDataSource(dataSource); 76 77 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init avsource failed"); 78 79 return sourceImpl; 80} 81 82int32_t AVSourceImpl::InitWithURI(const std::string &uri) 83{ 84 AVCODEC_SYNC_TRACE; 85 86 CHECK_AND_RETURN_RET_LOG(mediaDemuxer == nullptr, AVCS_ERR_INVALID_OPERATION, "Has been used by demuxer"); 87 mediaDemuxer = std::make_shared<MediaDemuxer>(); 88 mediaDemuxer->SetPlayerId("AVSource_URI"); 89 CHECK_AND_RETURN_RET_LOG(mediaDemuxer != nullptr, AVCS_ERR_INVALID_OPERATION, "Create mediaDemuxer failed"); 90 91 std::shared_ptr<MediaSource> mediaSource = std::make_shared<MediaSource>(uri); 92 Status ret = mediaDemuxer->SetDataSource(mediaSource); 93 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, StatusToAVCodecServiceErrCode(ret), "Set data source failed"); 94 95 sourceUri = uri; 96 return AVCS_ERR_OK; 97} 98 99int32_t AVSourceImpl::InitWithFD(int32_t fd, int64_t offset, int64_t size) 100{ 101 AVCODEC_SYNC_TRACE; 102 103 CHECK_AND_RETURN_RET_LOG(mediaDemuxer == nullptr, AVCS_ERR_INVALID_OPERATION, "Has been used by demuxer"); 104 CHECK_AND_RETURN_RET_LOG(fd >= 0, AVCS_ERR_INVALID_VAL, "Input fd is negative"); 105 if (fd <= STDERR_FILENO) { 106 AVCODEC_LOGW("Using special fd: %{public}d, isatty: %{public}d", fd, isatty(fd)); 107 } 108 CHECK_AND_RETURN_RET_LOG(offset >= 0, AVCS_ERR_INVALID_VAL, "Input offset is negative"); 109 CHECK_AND_RETURN_RET_LOG(size > 0, AVCS_ERR_INVALID_VAL, "Input size must be greater than zero"); 110 int32_t flag = fcntl(fd, F_GETFL, 0); 111 CHECK_AND_RETURN_RET_LOG(flag >= 0, AVCS_ERR_INVALID_VAL, "Get fd status failed"); 112 CHECK_AND_RETURN_RET_LOG( 113 (static_cast<uint32_t>(flag) & static_cast<uint32_t>(O_WRONLY)) != static_cast<uint32_t>(O_WRONLY), 114 AVCS_ERR_INVALID_VAL, "Fd is not permitted to read"); 115 CHECK_AND_RETURN_RET_LOG(lseek(fd, 0, SEEK_CUR) != -1, AVCS_ERR_INVALID_VAL, "Fd unseekable"); 116 117 std::string uri = "fd://" + std::to_string(fd) + "?offset=" + \ 118 std::to_string(offset) + "&size=" + std::to_string(size); 119 120 return InitWithURI(uri); 121} 122 123int32_t AVSourceImpl::InitWithDataSource(const std::shared_ptr<Media::IMediaDataSource> &dataSource) 124{ 125 AVCODEC_SYNC_TRACE; 126 127 CHECK_AND_RETURN_RET_LOG(mediaDemuxer == nullptr, AVCS_ERR_INVALID_OPERATION, "Has been used by demuxer"); 128 mediaDemuxer = std::make_shared<MediaDemuxer>(); 129 mediaDemuxer->SetPlayerId("AVSource_Data"); 130 CHECK_AND_RETURN_RET_LOG(mediaDemuxer != nullptr, AVCS_ERR_INVALID_OPERATION, "Create mediaDemuxer failed"); 131 132 std::shared_ptr<MediaSource> mediaSource = std::make_shared<MediaSource>(dataSource); 133 Status ret = mediaDemuxer->SetDataSource(mediaSource); 134 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, StatusToAVCodecServiceErrCode(ret), "Set data source failed"); 135 136 return AVCS_ERR_OK; 137} 138 139AVSourceImpl::AVSourceImpl() 140{ 141 AVCODEC_LOGD("Create instances 0x%{public}06" PRIXPTR, FAKE_POINTER(this)); 142} 143 144AVSourceImpl::~AVSourceImpl() 145{ 146 if (mediaDemuxer != nullptr) { 147 mediaDemuxer = nullptr; 148 } 149 AVCODEC_LOGD("Destroy instances 0x%{public}06" PRIXPTR, FAKE_POINTER(this)); 150} 151 152int32_t AVSourceImpl::GetSourceFormat(OHOS::Media::Format &format) 153{ 154 AVCODEC_SYNC_TRACE; 155 AVCODEC_LOGD("Get source format"); 156 157 CHECK_AND_RETURN_RET_LOG(mediaDemuxer != nullptr, AVCS_ERR_INVALID_OPERATION, "MediaDemuxer does not exist"); 158 159 std::shared_ptr<OHOS::Media::Meta> mediaInfo = mediaDemuxer->GetGlobalMetaInfo(); 160 CHECK_AND_RETURN_RET_LOG(mediaInfo != nullptr, AVCS_ERR_INVALID_OPERATION, "Parse media info failed"); 161 162 bool set = format.SetMeta(mediaInfo); 163 CHECK_AND_RETURN_RET_LOG(set, AVCS_ERR_INVALID_OPERATION, "Convert meta failed"); 164 165 return AVCS_ERR_OK; 166} 167 168int32_t AVSourceImpl::GetTrackFormat(OHOS::Media::Format &format, uint32_t trackIndex) 169{ 170 AVCODEC_SYNC_TRACE; 171 AVCODEC_LOGD("Get track %{public}u format", trackIndex); 172 173 CHECK_AND_RETURN_RET_LOG(mediaDemuxer != nullptr, AVCS_ERR_INVALID_OPERATION, "MediaDemuxer does not exist"); 174 175 std::vector<std::shared_ptr<Meta>> streamsInfo = mediaDemuxer->GetStreamMetaInfo(); 176 CHECK_AND_RETURN_RET_LOG(trackIndex < streamsInfo.size(), AVCS_ERR_INVALID_VAL, 177 "Just have %{public}zu tracks. index is out of range", streamsInfo.size()); 178 179 bool set = format.SetMeta(streamsInfo[trackIndex]); 180 CHECK_AND_RETURN_RET_LOG(set, AVCS_ERR_INVALID_OPERATION, "Convert meta failed"); 181 182 return AVCS_ERR_OK; 183} 184 185int32_t AVSourceImpl::GetUserMeta(OHOS::Media::Format &format) 186{ 187 AVCODEC_SYNC_TRACE; 188 AVCODEC_LOGD("get user meta"); 189 190 CHECK_AND_RETURN_RET_LOG(mediaDemuxer != nullptr, AVCS_ERR_INVALID_OPERATION, "MediaDemuxer does not exist"); 191 192 std::shared_ptr<OHOS::Media::Meta> userDataMeta = mediaDemuxer->GetUserMeta(); 193 CHECK_AND_RETURN_RET_LOG(userDataMeta != nullptr, AVCS_ERR_INVALID_OPERATION, "Parse user info failed"); 194 195 bool set = format.SetMeta(userDataMeta); 196 CHECK_AND_RETURN_RET_LOG(set, AVCS_ERR_INVALID_OPERATION, "Convert meta failed"); 197 198 return AVCS_ERR_OK; 199} 200} // namespace MediaAVCodec 201} // namespace OHOS