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