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 "native_avdemuxer.h"
17 #include <memory>
18 #include "av_common.h"
19 #include "avcodec_errors.h"
20 #include "avcodec_log.h"
21 #include "avdemuxer.h"
22 #include "common/native_mfmagic.h"
23 #include "native_avmagic.h"
24 #include "native_object.h"
25 #include "native_drm_common.h"
26 namespace {
27     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_DEMUXER, "NativeAVDemuxer"};
28 }
29 
30 using namespace OHOS::MediaAVCodec;
31 
32 namespace NativeDrmTools {
ProcessApplicationDrmInfo(DRM_MediaKeySystemInfo *info, const std::multimap<std::string, std::vector<uint8_t>> &drmInfoMap)33 static int32_t ProcessApplicationDrmInfo(DRM_MediaKeySystemInfo *info,
34     const std::multimap<std::string, std::vector<uint8_t>> &drmInfoMap)
35 {
36     uint32_t count = drmInfoMap.size();
37     if (count <= 0 || count > MAX_PSSH_INFO_COUNT) {
38         return AV_ERR_INVALID_VAL;
39     }
40     CHECK_AND_RETURN_RET_LOG(info != nullptr, AV_ERR_INVALID_VAL, "Info is nullptr");
41 
42     info->psshCount = count;
43     uint32_t index = 0;
44     for (auto &item : drmInfoMap) {
45         const uint32_t step = 2;
46         errno_t ret = memset_s(info->psshInfo[index].uuid, DRM_UUID_LEN, 0x00, DRM_UUID_LEN);
47         CHECK_AND_RETURN_RET_LOG(ret == EOK, AV_ERR_INVALID_VAL, "Memset uuid failed");
48         for (uint32_t i = 0; i < item.first.size(); i += step) {
49             std::string byteString = item.first.substr(i, step);
50             unsigned char uuidByte = (unsigned char)strtol(byteString.c_str(), NULL, DRM_UUID_LEN);
51             info->psshInfo[index].uuid[i / step] = uuidByte;
52         }
53 
54         info->psshInfo[index].dataLen = static_cast<int32_t>(item.second.size());
55 
56         ret = memset_s(info->psshInfo[index].data, MAX_PSSH_DATA_LEN, 0x00, MAX_PSSH_DATA_LEN);
57         CHECK_AND_RETURN_RET_LOG(ret == EOK, AV_ERR_INVALID_VAL, "Memset pssh failed");
58         CHECK_AND_RETURN_RET_LOG(item.second.size() <= MAX_PSSH_DATA_LEN, AV_ERR_INVALID_VAL, "Pssh is too large");
59         ret = memcpy_s(info->psshInfo[index].data, item.second.size(), static_cast<const void *>(item.second.data()),
60             item.second.size());
61         CHECK_AND_RETURN_RET_LOG(ret == EOK, AV_ERR_INVALID_VAL, "Pssh is too large");
62 
63         index++;
64     }
65     return AV_ERR_OK;
66 }
67 } // namespace NativeDrmTools
68 
69 class NativeDemuxerCallback;
70 struct DemuxerObject : public OH_AVDemuxer {
DemuxerObjectDemuxerObject71     explicit DemuxerObject(const std::shared_ptr<AVDemuxer> &demuxer)
72         : OH_AVDemuxer(AVMagic::AVCODEC_MAGIC_AVDEMUXER), demuxer_(demuxer) {}
73     ~DemuxerObject() = default;
74 
75     const std::shared_ptr<AVDemuxer> demuxer_;
76     std::shared_ptr<NativeDemuxerCallback> callback_;
77 };
78 
79 class NativeDemuxerCallback : public AVDemuxerCallback {
80 public:
NativeDemuxerCallback(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfoCallback cb)81     explicit NativeDemuxerCallback(OH_AVDemuxer *demuxer,
82         DRM_MediaKeySystemInfoCallback cb) : demuxer_(demuxer), callback_(cb), callbackObj_(nullptr)
83     {
84     }
85 
NativeDemuxerCallback(OH_AVDemuxer *demuxer, Demuxer_MediaKeySystemInfoCallback cbObj)86     explicit NativeDemuxerCallback(OH_AVDemuxer *demuxer,
87         Demuxer_MediaKeySystemInfoCallback cbObj) : demuxer_(demuxer), callback_(nullptr), callbackObj_(cbObj)
88     {
89     }
90 
91     virtual ~NativeDemuxerCallback() = default;
92 
93     void OnDrmInfoChanged(const std::multimap<std::string, std::vector<uint8_t>> &drmInfo) override
94     {
95         AVCODEC_LOGI("NativeDemuxerCallback OnDrmInfoChanged is on call");
96         std::unique_lock<std::shared_mutex> lock(mutex_);
97         CHECK_AND_RETURN_LOG(demuxer_ != nullptr, "AVDemuxer is nullptr");
98 
99         DRM_MediaKeySystemInfo info;
100         int32_t ret = NativeDrmTools::ProcessApplicationDrmInfo(&info, drmInfo);
101         CHECK_AND_RETURN_LOG(ret == AV_ERR_OK, "ProcessApplicationDrmInfo failed");
102 
103         CHECK_AND_RETURN_LOG(callback_ != nullptr || callbackObj_ != nullptr, "Hasn't register any drm callback");
104         if (callback_ != nullptr) {
105             callback_(&info);
106         }
107         if (callbackObj_ != nullptr) {
108             callbackObj_(demuxer_, &info);
109         }
110     }
111 
112 private:
113     std::shared_mutex mutex_;
114     struct OH_AVDemuxer *demuxer_;
115     DRM_MediaKeySystemInfoCallback callback_;
116     Demuxer_MediaKeySystemInfoCallback callbackObj_;
117 };
118 
OH_AVDemuxer_CreateWithSource(OH_AVSource *source)119 struct OH_AVDemuxer *OH_AVDemuxer_CreateWithSource(OH_AVSource *source)
120 {
121     CHECK_AND_RETURN_RET_LOG(source != nullptr, nullptr, "Input source is nullptr");
122     CHECK_AND_RETURN_RET_LOG(source->magic_ == AVMagic::AVCODEC_MAGIC_AVSOURCE, nullptr, "Magic error");
123 
124     struct AVSourceObject *sourceObj = reinterpret_cast<AVSourceObject *>(source);
125     CHECK_AND_RETURN_RET_LOG(sourceObj != nullptr, nullptr, "Create sourceObject is nullptr");
126 
127     std::shared_ptr<AVDemuxer> demuxer = AVDemuxerFactory::CreateWithSource(sourceObj->source_);
128     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, nullptr, "New avdemuxer failed");
129 
130     struct DemuxerObject *object = new(std::nothrow) DemuxerObject(demuxer);
131     CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "New demuxerObject failed");
132 
133     return object;
134 }
135 
OH_AVDemuxer_Destroy(OH_AVDemuxer *demuxer)136 OH_AVErrCode OH_AVDemuxer_Destroy(OH_AVDemuxer *demuxer)
137 {
138     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
139     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
140 
141     delete demuxer;
142     return AV_ERR_OK;
143 }
144 
OH_AVDemuxer_SelectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex)145 OH_AVErrCode OH_AVDemuxer_SelectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex)
146 {
147     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
148     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
149 
150     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
151     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
152     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
153 
154     int32_t ret = demuxerObj->demuxer_->SelectTrackByID(trackIndex);
155     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
156                              "AVDemuxer select track failed");
157 
158     return AV_ERR_OK;
159 }
160 
OH_AVDemuxer_UnselectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex)161 OH_AVErrCode OH_AVDemuxer_UnselectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex)
162 {
163     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
164     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
165 
166     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
167     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
168     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
169 
170     int32_t ret = demuxerObj->demuxer_->UnselectTrackByID(trackIndex);
171     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
172                              "AVDemuxer unselect track failed");
173 
174     return AV_ERR_OK;
175 }
176 
OH_AVDemuxer_ReadSample(OH_AVDemuxer *demuxer, uint32_t trackIndex, OH_AVMemory *sample, OH_AVCodecBufferAttr *info)177 OH_AVErrCode OH_AVDemuxer_ReadSample(OH_AVDemuxer *demuxer, uint32_t trackIndex,
178     OH_AVMemory *sample, OH_AVCodecBufferAttr *info)
179 {
180     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
181     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
182 
183     CHECK_AND_RETURN_RET_LOG(sample != nullptr && sample->memory_ != nullptr, AV_ERR_INVALID_VAL, "Sample is nullptr");
184     CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_SHARED_MEMORY, AV_ERR_INVALID_VAL, "Magic error");
185     CHECK_AND_RETURN_RET_LOG(info != nullptr, AV_ERR_INVALID_VAL, "Info is nullptr");
186 
187     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
188     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
189     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
190 
191     struct AVCodecBufferInfo bufferInfoInner;
192     uint32_t bufferFlag = (uint32_t)(AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE);
193     int32_t ret = demuxerObj->demuxer_->ReadSample(trackIndex, sample->memory_, bufferInfoInner, bufferFlag);
194     info->pts = bufferInfoInner.presentationTimeUs;
195     info->size = bufferInfoInner.size;
196     info->offset = bufferInfoInner.offset;
197     info->flags = bufferFlag;
198 
199     CHECK_AND_RETURN_RET_LOG(ret != AVCS_ERR_NO_MEMORY, AV_ERR_NO_MEMORY, "Sample size is too small");
200     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
201                              "AVDemuxer read failed");
202 
203     return AV_ERR_OK;
204 }
205 
OH_AVDemuxer_ReadSampleBuffer(OH_AVDemuxer *demuxer, uint32_t trackIndex, OH_AVBuffer *sample)206 OH_AVErrCode OH_AVDemuxer_ReadSampleBuffer(OH_AVDemuxer *demuxer, uint32_t trackIndex, OH_AVBuffer *sample)
207 {
208     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
209     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
210 
211     CHECK_AND_RETURN_RET_LOG(sample != nullptr && sample->buffer_ != nullptr, AV_ERR_INVALID_VAL, "Sample is nullptr");
212     CHECK_AND_RETURN_RET_LOG(sample->magic_ == MFMagic::MFMAGIC_AVBUFFER, AV_ERR_INVALID_VAL, "Magic error");
213 
214     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
215     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
216     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
217 
218     int32_t ret = demuxerObj->demuxer_->ReadSampleBuffer(trackIndex, sample->buffer_);
219     CHECK_AND_RETURN_RET_LOG(ret != AVCS_ERR_NO_MEMORY, AV_ERR_NO_MEMORY, "Sample size is too small");
220     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
221                              "AVDemuxer read failed");
222 
223     return AV_ERR_OK;
224 }
225 
OH_AVDemuxer_SeekToTime(OH_AVDemuxer *demuxer, int64_t millisecond, OH_AVSeekMode mode)226 OH_AVErrCode OH_AVDemuxer_SeekToTime(OH_AVDemuxer *demuxer, int64_t millisecond, OH_AVSeekMode mode)
227 {
228     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
229     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
230 
231     CHECK_AND_RETURN_RET_LOG(millisecond >= 0, AV_ERR_INVALID_VAL, "Millisecond is negative");
232 
233     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
234     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
235     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
236 
237     int32_t ret = demuxerObj->demuxer_->SeekToTime(millisecond, static_cast<OHOS::Media::SeekMode>(mode));
238     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
239                              "AVDemuxer seek failed");
240 
241     return AV_ERR_OK;
242 }
243 
OH_AVDemuxer_SetMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfoCallback callback)244 OH_AVErrCode OH_AVDemuxer_SetMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer,
245     DRM_MediaKeySystemInfoCallback callback)
246 {
247     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
248     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
249 
250     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
251     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
252     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
253 
254     demuxerObj->callback_ = std::make_shared<NativeDemuxerCallback>(demuxer, callback);
255     int32_t ret = demuxerObj->demuxer_->SetCallback(demuxerObj->callback_);
256     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
257         "AVDemuxer set callback failed");
258     return AV_ERR_OK;
259 }
260 
OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer, Demuxer_MediaKeySystemInfoCallback callback)261 OH_AVErrCode OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer,
262     Demuxer_MediaKeySystemInfoCallback callback)
263 {
264     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
265     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
266 
267     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
268     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
269     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
270 
271     demuxerObj->callback_ = std::make_shared<NativeDemuxerCallback>(demuxer, callback);
272     int32_t ret = demuxerObj->demuxer_->SetCallback(demuxerObj->callback_);
273     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
274         "AVDemuxer set callback failed");
275     return AV_ERR_OK;
276 }
277 
OH_AVDemuxer_GetMediaKeySystemInfo(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *mediaKeySystemInfo)278 OH_AVErrCode OH_AVDemuxer_GetMediaKeySystemInfo(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *mediaKeySystemInfo)
279 {
280     CHECK_AND_RETURN_RET_LOG(demuxer != nullptr, AV_ERR_INVALID_VAL, "Input demuxer is nullptr");
281     CHECK_AND_RETURN_RET_LOG(demuxer->magic_ == AVMagic::AVCODEC_MAGIC_AVDEMUXER, AV_ERR_INVALID_VAL, "Magic error");
282 
283     struct DemuxerObject *demuxerObj = reinterpret_cast<DemuxerObject *>(demuxer);
284     CHECK_AND_RETURN_RET_LOG(demuxerObj != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
285     CHECK_AND_RETURN_RET_LOG(demuxerObj->demuxer_ != nullptr, AV_ERR_INVALID_VAL, "Get demuxerObject failed");
286 
287     std::multimap<std::string, std::vector<uint8_t>> drmInfos;
288     int32_t ret = demuxerObj->demuxer_->GetMediaKeySystemInfo(drmInfos);
289     CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
290         "AVDemuxer GetMediaKeySystemInfo failed");
291     CHECK_AND_RETURN_RET_LOG(!drmInfos.empty(), AV_ERR_OK, "DrmInfo is null");
292 
293     ret = NativeDrmTools::ProcessApplicationDrmInfo(mediaKeySystemInfo, drmInfos);
294     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AV_ERR_INVALID_VAL, "ProcessApplicationDrmInfo failed");
295 
296     return AV_ERR_OK;
297 }