1 /*
2  * Copyright (c) 2024 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 "OHAVMetadataBuilder.h"
16 #include "avsession_log.h"
17 
18 using namespace OHOS::AVSession;
19 
SetTitle(const std::string & title)20 AVMetadata_Result OHAVMetadataBuilder::SetTitle(const std::string &title)
21 {
22     title_ = title;
23     return AVMETADATA_SUCCESS;
24 }
25 
SetArtist(const std::string & artist)26 AVMetadata_Result OHAVMetadataBuilder::SetArtist(const std::string &artist)
27 {
28     artist_ = artist;
29     return AVMETADATA_SUCCESS;
30 }
31 
SetAuthor(const std::string & author)32 AVMetadata_Result OHAVMetadataBuilder::SetAuthor(const std::string &author)
33 {
34     author_ = author;
35     return AVMETADATA_SUCCESS;
36 }
37 
SetAlbum(const std::string & album)38 AVMetadata_Result OHAVMetadataBuilder::SetAlbum(const std::string &album)
39 {
40     album_ = album;
41     return AVMETADATA_SUCCESS;
42 }
43 
SetWriter(const std::string & writer)44 AVMetadata_Result OHAVMetadataBuilder::SetWriter(const std::string &writer)
45 {
46     writer_ = writer;
47     return AVMETADATA_SUCCESS;
48 }
49 
SetComposer(const std::string & composer)50 AVMetadata_Result OHAVMetadataBuilder::SetComposer(const std::string &composer)
51 {
52     composer_ = composer;
53     return AVMETADATA_SUCCESS;
54 }
55 
SetDuration(int64_t duration)56 AVMetadata_Result OHAVMetadataBuilder::SetDuration(int64_t duration)
57 {
58     duration_ = duration;
59     return AVMETADATA_SUCCESS;
60 }
61 
SetMediaImageUri(const std::string & mediaImageUri)62 AVMetadata_Result OHAVMetadataBuilder::SetMediaImageUri(const std::string &mediaImageUri)
63 {
64     mediaImageUri_ = mediaImageUri;
65     return AVMETADATA_SUCCESS;
66 }
67 
SetSubtitle(const std::string & subtitle)68 AVMetadata_Result OHAVMetadataBuilder::SetSubtitle(const std::string &subtitle)
69 {
70     subtitle_ = subtitle;
71     return AVMETADATA_SUCCESS;
72 }
73 
SetDescription(const std::string & description)74 AVMetadata_Result OHAVMetadataBuilder::SetDescription(const std::string &description)
75 {
76     description_ = description;
77     return AVMETADATA_SUCCESS;
78 }
79 
SetLyric(const std::string & lyric)80 AVMetadata_Result OHAVMetadataBuilder::SetLyric(const std::string &lyric)
81 {
82     lyric_ = lyric;
83     return AVMETADATA_SUCCESS;
84 }
85 
SetAssetId(const std::string & assetId)86 AVMetadata_Result OHAVMetadataBuilder::SetAssetId(const std::string &assetId)
87 {
88     assetId_ = assetId;
89     return AVMETADATA_SUCCESS;
90 }
91 
SetSkipIntervals(AVMetadata_SkipIntervals intervals)92 AVMetadata_Result OHAVMetadataBuilder::SetSkipIntervals(AVMetadata_SkipIntervals intervals)
93 {
94     switch (intervals) {
95         case SECONDS_10:
96         case SECONDS_15:
97         case SECONDS_30:
98             intervals_ = intervals;
99             return AVMETADATA_SUCCESS;
100         default:
101             SLOGE("Failed to set skip intervals: Invalid skip intervals value: %d", intervals);
102             return AVMETADATA_ERROR_INVALID_PARAM;
103     }
104 }
105 
SetDisplayTags(int32_t tags)106 AVMetadata_Result OHAVMetadataBuilder::SetDisplayTags(int32_t tags)
107 {
108     tags_ = tags;
109     return AVMETADATA_SUCCESS;
110 }
111 
WriteCallback(std::uint8_t * ptr,size_t size,size_t nmemb,std::vector<std::uint8_t> * imgBuffer)112 size_t OHAVMetadataBuilder::WriteCallback(std::uint8_t *ptr, size_t size, size_t nmemb,
113                                           std::vector<std::uint8_t> *imgBuffer)
114 {
115     size_t realsize = size * nmemb;
116     imgBuffer->reserve(realsize + imgBuffer->capacity());
117     for (size_t i = 0; i < realsize; i++) {
118         imgBuffer->push_back(ptr[i]);
119     }
120     return realsize;
121 }
122 
CurlSetRequestOptions(std::vector<std::uint8_t> & imgBuffer,const std::string uri)123 bool OHAVMetadataBuilder::CurlSetRequestOptions(std::vector<std::uint8_t>& imgBuffer, const std::string uri)
124 {
125     CURL *easyHandle_ = curl_easy_init();
126     if (easyHandle_) {
127         // set request options
128         curl_easy_setopt(easyHandle_, CURLOPT_URL, uri.c_str());
129         curl_easy_setopt(easyHandle_, CURLOPT_CONNECTTIMEOUT, OHAVMetadataBuilder::TIME_OUT_SECOND);
130         curl_easy_setopt(easyHandle_, CURLOPT_SSL_VERIFYPEER, 0L);
131         curl_easy_setopt(easyHandle_, CURLOPT_SSL_VERIFYHOST, 0L);
132         curl_easy_setopt(easyHandle_, CURLOPT_CAINFO, "/etc/ssl/certs/" "cacert.pem");
133         curl_easy_setopt(easyHandle_, CURLOPT_HTTPGET, 1L);
134         curl_easy_setopt(easyHandle_, CURLOPT_WRITEFUNCTION, OHAVMetadataBuilder::WriteCallback);
135         curl_easy_setopt(easyHandle_, CURLOPT_WRITEDATA, &imgBuffer);
136 
137         // perform request
138         CURLcode res = curl_easy_perform(easyHandle_);
139         if (res != CURLE_OK) {
140             SLOGI("DoDownload curl easy_perform failure: %{public}s\n", curl_easy_strerror(res));
141             curl_easy_cleanup(easyHandle_);
142             easyHandle_ = nullptr;
143             return false;
144         } else {
145             int64_t httpCode = 0;
146             curl_easy_getinfo(easyHandle_, CURLINFO_RESPONSE_CODE, &httpCode);
147             SLOGI("DoDownload Http result " "%{public}" PRId64, httpCode);
148             CHECK_AND_RETURN_RET_LOG(httpCode < OHAVMetadataBuilder::HTTP_ERROR_CODE, false, "recv Http ERROR");
149             curl_easy_cleanup(easyHandle_);
150             easyHandle_ = nullptr;
151             return true;
152         }
153     }
154     return false;
155 }
156 
DoDownloadInCommon(std::shared_ptr<Media::PixelMap> & pixelMap,const std::string uri)157 bool OHAVMetadataBuilder::DoDownloadInCommon(std::shared_ptr<Media::PixelMap>& pixelMap, const std::string uri)
158 {
159     std::vector<std::uint8_t> imgBuffer(0);
160     if (CurlSetRequestOptions(imgBuffer, uri) == true) {
161         std::uint8_t* buffer = (std::uint8_t*) calloc(imgBuffer.size(), sizeof(uint8_t));
162         if (buffer == nullptr) {
163             SLOGE("buffer malloc fail");
164             free(buffer);
165             return false;
166         }
167         std::copy(imgBuffer.begin(), imgBuffer.end(), buffer);
168         uint32_t errorCode = 0;
169         Media::SourceOptions opts;
170         SLOGD("DoDownload get size %{public}d", static_cast<int>(imgBuffer.size()));
171         auto imageSource = Media::ImageSource::CreateImageSource(buffer, imgBuffer.size(), opts, errorCode);
172         free(buffer);
173         if (errorCode || !imageSource) {
174             SLOGE("DoDownload create imageSource fail: %{public}u", errorCode);
175             return false;
176         }
177         Media::DecodeOptions decodeOpts;
178         pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
179         if (errorCode || pixelMap == nullptr) {
180             SLOGE("DoDownload creatPix fail: %{public}u, %{public}d", errorCode, static_cast<int>(pixelMap != nullptr));
181             return false;
182         }
183         return true;
184     }
185     return false;
186 }
187 
DoDownload(AVMetaData & metadata,const std::string uri)188 int32_t OHAVMetadataBuilder::DoDownload(AVMetaData& metadata, const std::string uri)
189 {
190     std::shared_ptr<Media::PixelMap> pixelMap = nullptr;
191     bool ret = OHAVMetadataBuilder::DoDownloadInCommon(pixelMap, uri);
192     if (ret && pixelMap != nullptr) {
193         SLOGI("DoDownload success");
194         metadata.SetMediaImage(AVSessionPixelMapAdapter::ConvertToInner(pixelMap));
195         return AV_SESSION_ERR_SUCCESS;
196     }
197 
198     return AV_SESSION_ERR_SERVICE_EXCEPTION;
199 }
200 
GenerateAVMetadata(OH_AVMetadata ** avMetadata)201 AVMetadata_Result OHAVMetadataBuilder::GenerateAVMetadata(OH_AVMetadata** avMetadata)
202 {
203     CHECK_AND_RETURN_RET_LOG(avMetadata != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "avMetadata is null");
204 
205     AVMetaData* metadata = new AVMetaData();
206     if (metadata == nullptr) {
207         SLOGE("Failed to allocate memory for AVMetaData");
208         *avMetadata = nullptr;
209         return AVMETADATA_ERROR_NO_MEMORY;
210     }
211 
212     switch (intervals_) {
213         case SECONDS_10:
214             metadata->SetSkipIntervals(AVMetaData::SECONDS_10);
215             break;
216         case SECONDS_15:
217             metadata->SetSkipIntervals(AVMetaData::SECONDS_15);
218             break;
219         case SECONDS_30:
220             metadata->SetSkipIntervals(AVMetaData::SECONDS_30);
221             break;
222         default:
223             SLOGE("Failed to generate avMetadata: Unsupported skip intervals: %d", intervals_);
224             delete metadata;
225             *avMetadata = nullptr;
226             return AVMETADATA_ERROR_INVALID_PARAM;
227     }
228 
229     metadata->SetTitle(title_);
230     metadata->SetArtist(artist_);
231     metadata->SetAuthor(author_);
232     metadata->SetAlbum(album_);
233     metadata->SetWriter(writer_);
234     metadata->SetComposer(composer_);
235     metadata->SetDuration(duration_);
236     metadata->SetMediaImageUri(mediaImageUri_);
237     metadata->SetSubTitle(subtitle_);
238     metadata->SetDescription(description_);
239     metadata->SetLyric(lyric_);
240     metadata->SetAssetId(assetId_);
241     metadata->SetDisplayTags(tags_);
242 
243     DoDownload(*metadata, mediaImageUri_);
244 
245     *avMetadata = reinterpret_cast<OH_AVMetadata*>(metadata);
246 
247     return AVMETADATA_SUCCESS;
248 }
249 
OH_AVMetadataBuilder_Create(OH_AVMetadataBuilder ** builder)250 AVMetadata_Result OH_AVMetadataBuilder_Create(OH_AVMetadataBuilder** builder)
251 {
252     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
253 
254     OHAVMetadataBuilder* metadata = new OHAVMetadataBuilder();
255     if (metadata == nullptr) {
256         SLOGE("Failed to allocate memory for OHAVMetadataBuilder");
257         return AVMETADATA_ERROR_NO_MEMORY;
258     }
259 
260     *builder = reinterpret_cast<OH_AVMetadataBuilder*>(metadata);
261     return AVMETADATA_SUCCESS;
262 }
263 
OH_AVMetadataBuilder_Destroy(OH_AVMetadataBuilder * builder)264 AVMetadata_Result OH_AVMetadataBuilder_Destroy(OH_AVMetadataBuilder* builder)
265 {
266     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
267     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
268     delete metadata;
269     return AVMETADATA_SUCCESS;
270 }
271 
OH_AVMetadataBuilder_SetTitle(OH_AVMetadataBuilder * builder,const char * title)272 AVMetadata_Result OH_AVMetadataBuilder_SetTitle(OH_AVMetadataBuilder* builder, const char* title)
273 {
274     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
275     CHECK_AND_RETURN_RET_LOG(title != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "title is null");
276     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
277     return metadata->SetTitle(title);
278 }
279 
OH_AVMetadataBuilder_SetArtist(OH_AVMetadataBuilder * builder,const char * artist)280 AVMetadata_Result OH_AVMetadataBuilder_SetArtist(OH_AVMetadataBuilder* builder, const char* artist)
281 {
282     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
283     CHECK_AND_RETURN_RET_LOG(artist != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "artist is null");
284     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
285     return metadata->SetArtist(artist);
286 }
287 
OH_AVMetadataBuilder_SetAuthor(OH_AVMetadataBuilder * builder,const char * author)288 AVMetadata_Result OH_AVMetadataBuilder_SetAuthor(OH_AVMetadataBuilder* builder, const char* author)
289 {
290     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
291     CHECK_AND_RETURN_RET_LOG(author != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "author is null");
292     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
293     return metadata->SetAuthor(author);
294 }
295 
OH_AVMetadataBuilder_SetAlbum(OH_AVMetadataBuilder * builder,const char * album)296 AVMetadata_Result OH_AVMetadataBuilder_SetAlbum(OH_AVMetadataBuilder* builder, const char* album)
297 {
298     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
299     CHECK_AND_RETURN_RET_LOG(album != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "album is null");
300     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
301     return metadata->SetAlbum(album);
302 }
303 
OH_AVMetadataBuilder_SetWriter(OH_AVMetadataBuilder * builder,const char * writer)304 AVMetadata_Result OH_AVMetadataBuilder_SetWriter(OH_AVMetadataBuilder* builder, const char* writer)
305 {
306     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
307     CHECK_AND_RETURN_RET_LOG(writer != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "writer is null");
308     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
309     return metadata->SetWriter(writer);
310 }
311 
OH_AVMetadataBuilder_SetComposer(OH_AVMetadataBuilder * builder,const char * composer)312 AVMetadata_Result OH_AVMetadataBuilder_SetComposer(OH_AVMetadataBuilder* builder, const char* composer)
313 {
314     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
315     CHECK_AND_RETURN_RET_LOG(composer != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "composer is null");
316     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
317     return metadata->SetComposer(composer);
318 }
319 
OH_AVMetadataBuilder_SetDuration(OH_AVMetadataBuilder * builder,int64_t duration)320 AVMetadata_Result OH_AVMetadataBuilder_SetDuration(OH_AVMetadataBuilder* builder, int64_t duration)
321 {
322     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
323     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
324     return metadata->SetDuration(duration);
325 }
326 
OH_AVMetadataBuilder_SetMediaImageUri(OH_AVMetadataBuilder * builder,const char * mediaImageUri)327 AVMetadata_Result OH_AVMetadataBuilder_SetMediaImageUri(OH_AVMetadataBuilder* builder, const char* mediaImageUri)
328 {
329     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
330     CHECK_AND_RETURN_RET_LOG(mediaImageUri != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "mediaImageUri is null");
331     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
332     return metadata->SetMediaImageUri(mediaImageUri);
333 }
334 
OH_AVMetadataBuilder_SetSubtitle(OH_AVMetadataBuilder * builder,const char * subtitle)335 AVMetadata_Result OH_AVMetadataBuilder_SetSubtitle(OH_AVMetadataBuilder* builder, const char* subtitle)
336 {
337     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
338     CHECK_AND_RETURN_RET_LOG(subtitle != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "subtitle is null");
339     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
340     return metadata->SetSubtitle(subtitle);
341 }
342 
OH_AVMetadataBuilder_SetDescription(OH_AVMetadataBuilder * builder,const char * description)343 AVMetadata_Result OH_AVMetadataBuilder_SetDescription(OH_AVMetadataBuilder* builder, const char* description)
344 {
345     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
346     CHECK_AND_RETURN_RET_LOG(description != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "description is null");
347     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
348     return metadata->SetDescription(description);
349 }
350 
OH_AVMetadataBuilder_SetLyric(OH_AVMetadataBuilder * builder,const char * lyric)351 AVMetadata_Result OH_AVMetadataBuilder_SetLyric(OH_AVMetadataBuilder* builder, const char* lyric)
352 {
353     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
354     CHECK_AND_RETURN_RET_LOG(lyric != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "lyric is null");
355     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
356     return metadata->SetLyric(lyric);
357 }
358 
OH_AVMetadataBuilder_SetAssetId(OH_AVMetadataBuilder * builder,const char * assetId)359 AVMetadata_Result OH_AVMetadataBuilder_SetAssetId(OH_AVMetadataBuilder* builder, const char* assetId)
360 {
361     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
362     CHECK_AND_RETURN_RET_LOG(assetId != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "assetId is null");
363     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
364     return metadata->SetAssetId(assetId);
365 }
366 
OH_AVMetadataBuilder_SetSkipIntervals(OH_AVMetadataBuilder * builder,AVMetadata_SkipIntervals intervals)367 AVMetadata_Result OH_AVMetadataBuilder_SetSkipIntervals(OH_AVMetadataBuilder* builder,
368                                                         AVMetadata_SkipIntervals intervals)
369 {
370     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
371     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
372     return metadata->SetSkipIntervals(intervals);
373 }
374 
OH_AVMetadataBuilder_SetDisplayTags(OH_AVMetadataBuilder * builder,int32_t tags)375 AVMetadata_Result OH_AVMetadataBuilder_SetDisplayTags(OH_AVMetadataBuilder* builder, int32_t tags)
376 {
377     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
378     if (tags != AVSESSION_DISPLAYTAG_AUDIO_VIVID) {
379         return AVMETADATA_ERROR_INVALID_PARAM;
380     }
381     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
382     return metadata->SetDisplayTags(tags);
383 }
384 
OH_AVMetadataBuilder_GenerateAVMetadata(OH_AVMetadataBuilder * builder,OH_AVMetadata ** avMetadata)385 AVMetadata_Result OH_AVMetadataBuilder_GenerateAVMetadata(OH_AVMetadataBuilder* builder,
386                                                           OH_AVMetadata** avMetadata)
387 {
388     CHECK_AND_RETURN_RET_LOG(builder != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "builder is null");
389     CHECK_AND_RETURN_RET_LOG(avMetadata != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "avMetadata is null");
390     OHAVMetadataBuilder* metadata = reinterpret_cast<OHAVMetadataBuilder*>(builder);
391     return metadata->GenerateAVMetadata(avMetadata);
392 }
393 
OH_AVMetadata_Destroy(OH_AVMetadata * avMetadata)394 AVMetadata_Result OH_AVMetadata_Destroy(OH_AVMetadata* avMetadata)
395 {
396     CHECK_AND_RETURN_RET_LOG(avMetadata != nullptr, AVMETADATA_ERROR_INVALID_PARAM, "avMetadata is null");
397     AVMetaData* metadata = reinterpret_cast<AVMetaData*>(avMetadata);
398     delete metadata;
399     return AVMETADATA_SUCCESS;
400 }