• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "av_thumbnail_generator.h"
17 
18 #include "buffer/avbuffer_common.h"
19 #include "common/media_source.h"
20 #include "ibuffer_consumer_listener.h"
21 #include "graphic_common_c.h"
22 #include "media_errors.h"
23 #include "media_log.h"
24 #include "media_description.h"
25 #include "meta/meta.h"
26 #include "meta/meta_key.h"
27 #include "plugin/plugin_time.h"
28 #include "sync_fence.h"
29 #include "uri_helper.h"
30 
31 #include "v1_0/cm_color_space.h"
32 #include "v1_0/hdr_static_metadata.h"
33 #include "v1_0/buffer_handle_meta_key_type.h"
34 
35 namespace {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVThumbnailGenerator" };
37 }
38 
39 namespace OHOS {
40 namespace Media {
41 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
42 using FileType = OHOS::Media::Plugins::FileType;
43 constexpr float BYTES_PER_PIXEL_YUV = 1.5;
44 constexpr int32_t RATE_UV = 2;
45 constexpr int32_t SHIFT_BITS_P010_2_NV12 = 8;
46 constexpr double VIDEO_FRAME_RATE = 2000.0;
47 constexpr int32_t MAX_WAIT_TIME_SECOND = 3;
48 constexpr uint32_t REQUEST_BUFFER_TIMEOUT = 0; // Requesting buffer overtimes 0ms means no retry
49 constexpr uint32_t ERROR_AGAIN_SLEEP_TIME_US = 1000;
50 const std::string AV_THUMBNAIL_GENERATOR_INPUT_BUFFER_QUEUE_NAME = "AVThumbnailGeneratorInputBufferQueue";
51 
52 class ThumnGeneratorCodecCallback : public OHOS::MediaAVCodec::MediaCodecCallback {
53 public:
ThumnGeneratorCodecCallback(std::shared_ptr<AVThumbnailGenerator> generator)54     explicit ThumnGeneratorCodecCallback(std::shared_ptr<AVThumbnailGenerator> generator) : generator_(generator) {}
55 
56     ~ThumnGeneratorCodecCallback() = default;
57 
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)58     void OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode) override
59     {
60         if (auto generator = generator_.lock()) {
61             generator->OnError(errorType, errorCode);
62         } else {
63             MEDIA_LOGE("invalid AVThumbnailGenerator");
64         }
65     }
66 
OnOutputFormatChanged(const MediaAVCodec::Format & format)67     void OnOutputFormatChanged(const MediaAVCodec::Format &format) override
68     {
69         if (auto generator = generator_.lock()) {
70             generator->OnOutputFormatChanged(format);
71         } else {
72             MEDIA_LOGE("invalid AVThumbnailGenerator");
73         }
74     }
75 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)76     void OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override
77     {
78         if (auto generator = generator_.lock()) {
79             generator->OnInputBufferAvailable(index, buffer);
80         } else {
81             MEDIA_LOGE("invalid AVThumbnailGenerator");
82         }
83     }
84 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)85     void OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override
86     {
87         if (auto generator = generator_.lock()) {
88             generator->OnOutputBufferAvailable(index, buffer);
89         } else {
90             MEDIA_LOGE("invalid AVThumbnailGenerator");
91         }
92     }
93 
94 private:
95     std::weak_ptr<AVThumbnailGenerator> generator_;
96 };
97 
98 class ThumbnailGeneratorAVBufferAvailableListener : public OHOS::Media::IConsumerListener {
99 public:
ThumbnailGeneratorAVBufferAvailableListener(std::shared_ptr<AVThumbnailGenerator> generator)100     explicit ThumbnailGeneratorAVBufferAvailableListener(std::shared_ptr<AVThumbnailGenerator> generator)
101         : generator_(generator)
102     {
103     }
104 
OnBufferAvailable()105     void OnBufferAvailable() override
106     {
107         if (auto generator = generator_.lock()) {
108             generator->AcquireAvailableInputBuffer();
109         } else {
110             MEDIA_LOGE("invalid AVThumbnailGenerator");
111         }
112     }
113 private:
114     std::weak_ptr<AVThumbnailGenerator> generator_;
115 };
116 
AVThumbnailGenerator(std::shared_ptr<MediaDemuxer> & mediaDemuxer,int32_t appUid,int32_t appPid,uint32_t appTokenId,uint64_t appFullTokenId)117 AVThumbnailGenerator::AVThumbnailGenerator(std::shared_ptr<MediaDemuxer> &mediaDemuxer, int32_t appUid, int32_t appPid,
118     uint32_t appTokenId, uint64_t appFullTokenId) : mediaDemuxer_(mediaDemuxer), appUid_(appUid), appPid_(appPid),
119     appTokenId_(appTokenId), appFullTokenId_(appFullTokenId)
120 {
121     MEDIA_LOGI("Constructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
122 }
123 
~AVThumbnailGenerator()124 AVThumbnailGenerator::~AVThumbnailGenerator()
125 {
126     MEDIA_LOGI("Destructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
127     Destroy();
128 }
129 
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)130 void AVThumbnailGenerator::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
131 {
132     MEDIA_LOGE("OnError errorType:%{public}d, errorCode:%{public}d", static_cast<int32_t>(errorType), errorCode);
133     {
134         std::scoped_lock lock(mutex_, queueMutex_);
135         stopProcessing_ = true;
136     }
137     cond_.notify_all();
138     bufferAvailableCond_.notify_all();
139 }
140 
InitDecoder()141 Status AVThumbnailGenerator::InitDecoder()
142 {
143     MEDIA_LOGD("Init decoder start.");
144     if (videoDecoder_ != nullptr) {
145         MEDIA_LOGD("AVThumbnailGenerator InitDecoder already.");
146         Format format;
147         format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, VIDEO_FRAME_RATE);
148         videoDecoder_->SetParameter(format);
149         videoDecoder_->Start();
150         return Status::OK;
151     }
152     Format format;
153     int32_t ret = 0;
154     std::shared_ptr<Media::Meta> callerInfo = std::make_shared<Media::Meta>();
155     callerInfo->SetData(Media::Tag::AV_CODEC_FORWARD_CALLER_PID, appPid_);
156     callerInfo->SetData(Media::Tag::AV_CODEC_FORWARD_CALLER_UID, appUid_);
157     callerInfo->SetData(Media::Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, appName_);
158     format.SetMeta(callerInfo);
159     ret = MediaAVCodec::VideoDecoderFactory::CreateByMime(trackMime_, format, videoDecoder_);
160     MEDIA_LOGI("VideoDecoderAdapter::Init CreateByMime errorCode %{public}d", ret);
161     CHECK_AND_RETURN_RET_LOG(videoDecoder_ != nullptr, Status::ERROR_NO_MEMORY, "Create videoDecoder_ is nullptr");
162     MEDIA_LOGI("appUid: %{public}d, appPid: %{public}d, appName: %{public}s", appUid_, appPid_, appName_.c_str());
163     CHECK_AND_RETURN_RET_LOG(trackInfo_ != nullptr, Status::ERROR_NULL_POINTER, "track info init failed");
164     Format trackFormat{};
165     if (fileType_ == FileType::AVI) {
166         trackInfo_->SetData(Tag::MEDIA_FILE_TYPE, FileType::AVI);
167     }
168     trackFormat.SetMeta(trackInfo_);
169     trackFormat.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
170     trackFormat.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
171     MEDIA_LOGI("0x%{public}06" PRIXPTR " Init decoder trackFormat width:%{public}d, height:%{public}d",
172                FAKE_POINTER(this), width_, height_);
173     trackFormat.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT,
174                             static_cast<int32_t>(Plugins::VideoPixelFormat::NV12));
175     trackFormat.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, VIDEO_FRAME_RATE);
176     videoDecoder_->Configure(trackFormat);
177     std::shared_ptr<MediaAVCodec::MediaCodecCallback> mediaCodecCallback =
178         std::make_shared<ThumnGeneratorCodecCallback>(shared_from_this());
179     videoDecoder_->SetCallback(mediaCodecCallback);
180     videoDecoder_->Prepare();
181     auto res = videoDecoder_->Start();
182     CHECK_AND_RETURN_RET(res == MSERR_OK, Status::ERROR_WRONG_STATE);
183     return Status::OK;
184 }
185 
Init()186 int32_t AVThumbnailGenerator::Init()
187 {
188     CHECK_AND_RETURN_RET_LOG(inputBufferQueue_ == nullptr, MSERR_OK, "InputBufferQueue already create");
189 
190     inputBufferQueue_ = AVBufferQueue::Create(0,
191         MemoryType::UNKNOWN_MEMORY, AV_THUMBNAIL_GENERATOR_INPUT_BUFFER_QUEUE_NAME, true);
192     CHECK_AND_RETURN_RET_LOG(inputBufferQueue_ != nullptr, MSERR_NO_MEMORY, "BufferQueue is nullptr");
193 
194     inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
195     CHECK_AND_RETURN_RET_LOG(inputBufferQueueProducer_ != nullptr, MSERR_UNKNOWN, "QueueProducer is nullptr");
196 
197     inputBufferQueueConsumer_ = inputBufferQueue_->GetConsumer();
198     CHECK_AND_RETURN_RET_LOG(inputBufferQueueConsumer_ != nullptr, MSERR_UNKNOWN, "QueueConsumer is nullptr");
199 
200     sptr<IConsumerListener> listener = new ThumbnailGeneratorAVBufferAvailableListener(shared_from_this());
201     CHECK_AND_RETURN_RET_LOG(listener != nullptr, MSERR_NO_MEMORY, "listener is nullptr");
202     inputBufferQueueConsumer_->SetBufferAvailableListener(listener);
203 
204     readTask_ = std::make_unique<Task>(std::string("AVThumbReadLoop"));
205     CHECK_AND_RETURN_RET_LOG(readTask_ != nullptr, MSERR_NO_MEMORY, "Task is nullptr");
206 
207     readTask_->RegisterJob([this] {return ReadLoop();});
208     readTask_->Start();
209 
210     return MSERR_OK;
211 }
212 
SetClientBundleName(std::string appName)213 void AVThumbnailGenerator::SetClientBundleName(std::string appName)
214 {
215     appName_ = appName;
216     return;
217 }
218 
AcquireAvailableInputBuffer()219 void AVThumbnailGenerator::AcquireAvailableInputBuffer()
220 {
221     CHECK_AND_RETURN_LOG(inputBufferQueueConsumer_ != nullptr, "QueueConsumer is nullptr");
222 
223     std::shared_ptr<AVBuffer> filledInputBuffer;
224     Status ret = inputBufferQueueConsumer_->AcquireBuffer(filledInputBuffer);
225     CHECK_AND_RETURN_LOG(ret == Status::OK, "AcquireBuffer fail");
226 
227     if (fileType_ == FileType::AVI) {
228         GetInputBufferDts(filledInputBuffer);
229     }
230     CHECK_AND_RETURN_LOG(filledInputBuffer != nullptr && filledInputBuffer->meta_ != nullptr,
231         "filledInputBuffer is invalid.");
232     uint32_t index;
233     CHECK_AND_RETURN_LOG(filledInputBuffer->meta_->GetData(Tag::BUFFER_INDEX, index), "get index failed.");
234 
235     CHECK_AND_RETURN_LOG(videoDecoder_ != nullptr, "videoDecoder_ is nullptr.");
236     if (videoDecoder_->QueueInputBuffer(index) != ERR_OK) {
237         MEDIA_LOGE("QueueInputBuffer failed, index: %{public}u,  bufferid: %{public}" PRIu64
238             ", pts: %{public}" PRIu64", flag: %{public}u", index, filledInputBuffer->GetUniqueId(),
239             filledInputBuffer->pts_, filledInputBuffer->flag_);
240     } else {
241         MEDIA_LOGD("QueueInputBuffer success, index: %{public}u,  bufferid: %{public}" PRIu64
242             ", pts: %{public}" PRIu64", flag: %{public}u", index, filledInputBuffer->GetUniqueId(),
243             filledInputBuffer->pts_, filledInputBuffer->flag_);
244     }
245 }
246 
GetInputBufferDts(std::shared_ptr<AVBuffer> & inputBuffer)247 void AVThumbnailGenerator::GetInputBufferDts(std::shared_ptr<AVBuffer> &inputBuffer)
248 {
249     CHECK_AND_RETURN_NOLOG(inputBuffer != nullptr);
250     std::unique_lock<std::mutex> lock(dtsQueMutex_);
251     inputBufferDtsQue_.push_back(inputBuffer->dts_);
252     MEDIA_LOGD("Inputbuffer DTS: %{public}" PRId64 " dtsQue_ size: %{public}" PRIu64,
253         inputBuffer->dts_, static_cast<uint64_t>(inputBufferDtsQue_.size()));
254 }
255 
InitMediaInfoFromGlobalMeta()256 void AVThumbnailGenerator::InitMediaInfoFromGlobalMeta()
257 {
258     auto meta = mediaDemuxer_->GetGlobalMetaInfo();
259     CHECK_AND_RETURN_LOG(meta != nullptr, "Global info is nullptr");
260     (void)meta->Get<Tag::MEDIA_DURATION>(duration_);
261     MEDIA_LOGI("%{public}" PRId64, duration_);
262     CHECK_AND_RETURN_NOLOG(meta->GetData(Tag::MEDIA_FILE_TYPE, fileType_));
263     MEDIA_LOGI("file type is: %{public}" PRId32, static_cast<int32_t>(fileType_));
264 }
265 
GetVideoTrackInfo()266 std::shared_ptr<Meta> AVThumbnailGenerator::GetVideoTrackInfo()
267 {
268     CHECK_AND_RETURN_RET(trackInfo_ == nullptr, trackInfo_);
269     CHECK_AND_RETURN_RET_LOG(mediaDemuxer_ != nullptr, nullptr, "GetTargetTrackInfo demuxer is nullptr");
270     InitMediaInfoFromGlobalMeta();
271     std::vector<std::shared_ptr<Meta>> trackInfos = mediaDemuxer_->GetStreamMetaInfo();
272     size_t trackCount = trackInfos.size();
273     CHECK_AND_RETURN_RET_LOG(trackCount > 0, nullptr, "GetTargetTrackInfo trackCount is invalid");
274     for (size_t index = 0; index < trackCount; index++) {
275         CHECK_AND_CONTINUE_LOG(trackInfos[index] != nullptr, "trackInfos[%{public}zu] is nullptr", index);
276         if (!(trackInfos[index]->GetData(Tag::MIME_TYPE, trackMime_))) {
277             MEDIA_LOGW("GetTargetTrackInfo get mime type failed %{public}s", trackMime_.c_str());
278             continue;
279         }
280         if (trackMime_.find("video/") == 0) {
281             Plugins::MediaType mediaType;
282             CHECK_AND_RETURN_RET_LOG(trackInfos[index]->GetData(Tag::MEDIA_TYPE, mediaType), nullptr,
283                                      "GetTargetTrackInfo failed to get mediaType, index:%{public}zu", index);
284             CHECK_AND_RETURN_RET_LOG(
285                 mediaType == Plugins::MediaType::VIDEO, nullptr,
286                 "GetTargetTrackInfo mediaType is not video, index:%{public}zu, mediaType:%{public}d", index,
287                 static_cast<int32_t>(mediaType));
288             CHECK_AND_RETURN_RET_LOG(trackInfos[index]->Get<Tag::VIDEO_FRAME_RATE>(frameRate_) && frameRate_ > 0,
289                 nullptr, "failed to get video frame rate");
290             trackIndex_ = index;
291             MEDIA_LOGI("0x%{public}06" PRIXPTR " GetTrackInfo success trackIndex_:%{public}zu, trackMime_:%{public}s",
292                        FAKE_POINTER(this), trackIndex_, trackMime_.c_str());
293             trackInfos[index]->Get<Tag::VIDEO_ROTATION>(rotation_);
294             trackInfos[index]->Get<Tag::VIDEO_ORIENTATION_TYPE>(orientation_);
295             MEDIA_LOGI("rotation is %{public}d, orientation is %{public}d", static_cast<int32_t>(rotation_),
296                 static_cast<int32_t>(orientation_));
297             return trackInfos[trackIndex_];
298         }
299     }
300     MEDIA_LOGW("GetTargetTrackInfo FAILED.");
301     return nullptr;
302 }
303 
OnOutputFormatChanged(const MediaAVCodec::Format & format)304 void AVThumbnailGenerator::OnOutputFormatChanged(const MediaAVCodec::Format &format)
305 {
306     MEDIA_LOGD("OnOutputFormatChanged");
307     outputFormat_ = format;
308     int32_t width = 0;
309     int32_t height = 0;
310     bool hasWidth = format.GetIntValue(Tag::VIDEO_PIC_WIDTH, width);
311     bool hasHeight = format.GetIntValue(Tag::VIDEO_PIC_HEIGHT, height);
312     CHECK_AND_RETURN_LOG(hasWidth && hasHeight, "OutputFormat doesn't have width or height");
313     width_ = width;
314     height_ = height;
315 }
316 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)317 void AVThumbnailGenerator::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
318 {
319     CHECK_AND_RETURN_LOG(buffer != nullptr && buffer->meta_ != nullptr, "meta_ is nullptr.");
320 
321     MEDIA_LOGD("OnInputBufferAvailable enter. index: %{public}u, bufferid: %{public}" PRIu64", pts: %{public}" PRIu64
322         ", flag: %{public}u", index, buffer->GetUniqueId(), buffer->pts_, buffer->flag_);
323 
324     buffer->meta_->SetData(Tag::BUFFER_INDEX, index);
325 
326     CHECK_AND_RETURN_LOG(inputBufferQueueConsumer_ != nullptr, "QueueConsumer is nullptr");
327 
328     if (stopProcessing_.load() || hasFetchedFrame_.load() || readErrorFlag_.load()) {
329         MEDIA_LOGD("stop or has fetched frame, need not queue input buffer");
330         return;
331     }
332 
333     {
334         std::unique_lock<std::mutex> lock(queueMutex_);
335         if (inputBufferQueueConsumer_->IsBufferInQueue(buffer)) {
336             if (inputBufferQueueConsumer_->ReleaseBuffer(buffer) != Status::OK) {
337                 MEDIA_LOGE("IsBufferInQueue ReleaseBuffer failed. index: %{public}u, bufferid: %{public}" PRIu64
338                     ", pts: %{public}" PRIu64", flag: %{public}u", index, buffer->GetUniqueId(),
339                     buffer->pts_, buffer->flag_);
340                 return;
341             } else {
342                 MEDIA_LOGD("IsBufferInQueue ReleaseBuffer success. index: %{public}u, bufferid: %{public}" PRIu64
343                     ", pts: %{public}" PRIu64", flag: %{public}u", index, buffer->GetUniqueId(),
344                     buffer->pts_, buffer->flag_);
345             }
346         } else {
347             uint32_t size = inputBufferQueueConsumer_->GetQueueSize() + 1;
348             MEDIA_LOGI("AttachBuffer enter. index: %{public}u,  size: %{public}u , bufferid: %{public}" PRIu64,
349                 index, size, buffer->GetUniqueId());
350             inputBufferQueueConsumer_->SetQueueSizeAndAttachBuffer(size, buffer, false);
351             bufferVector_.push_back(buffer);
352         }
353         isBufferAvailable_ = true;
354     }
355     bufferAvailableCond_.notify_all();
356 }
357 
ReadLoop()358 int64_t AVThumbnailGenerator::ReadLoop()
359 {
360     std::shared_ptr<AVBuffer> emptyBuffer = nullptr;
361     {
362         std::unique_lock<std::mutex> lock(queueMutex_);
363         bufferAvailableCond_.wait(lock, [this] {
364             return stopProcessing_.load() ||
365                    (!hasFetchedFrame_.load() && !readErrorFlag_.load() && isBufferAvailable_.load());
366         });
367 
368         CHECK_AND_RETURN_RET_LOG(!stopProcessing_.load(), StopTask(), "Stop Readloop");
369 
370         CHECK_AND_RETURN_RET_LOG(inputBufferQueueProducer_ != nullptr, StopTask(), "QueueProducer is nullptr");
371 
372         AVBufferConfig avBufferConfig;
373         auto res = inputBufferQueueProducer_->RequestBuffer(emptyBuffer, avBufferConfig, REQUEST_BUFFER_TIMEOUT);
374         if (res != Status::OK) {
375             isBufferAvailable_ = false;
376             return 0;
377         }
378     }
379 
380     CHECK_AND_RETURN_RET_LOG(mediaDemuxer_ != nullptr, StopTask(), "mediaDemuxer is nullptr");
381 
382     auto readSampleRes = mediaDemuxer_->ReadSample(trackIndex_, emptyBuffer);
383     if (readSampleRes != Status::OK && readSampleRes != Status::END_OF_STREAM && readSampleRes != Status::ERROR_AGAIN) {
384         {
385             std::unique_lock<std::mutex> lock(mutex_);
386             readErrorFlag_ = true;
387         }
388         cond_.notify_all();
389         inputBufferQueueProducer_->PushBuffer(emptyBuffer, false);
390         return 0;
391     }
392     if (readSampleRes == Status::ERROR_AGAIN) {
393         inputBufferQueueProducer_->PushBuffer(emptyBuffer, false);
394         return ERROR_AGAIN_SLEEP_TIME_US;
395     }
396     if (fileType_ == FileType::AVI) {
397         SetDemuxerOutputBufferPts(emptyBuffer);
398     }
399     inputBufferQueueProducer_->PushBuffer(emptyBuffer, true);
400     return 0;
401 }
402 
SetDemuxerOutputBufferPts(std::shared_ptr<AVBuffer> & outputBuffer)403 void AVThumbnailGenerator::SetDemuxerOutputBufferPts(std::shared_ptr<AVBuffer> &outputBuffer)
404 {
405     CHECK_AND_RETURN_NOLOG(outputBuffer != nullptr);
406     MEDIA_LOGD("OutputBuffer PTS: %{public}" PRId64 " DTS: %{public}" PRId64, outputBuffer->pts_, outputBuffer->dts_);
407     outputBuffer->pts_ = outputBuffer->dts_;
408 }
409 
StopTask()410 int64_t AVThumbnailGenerator::StopTask()
411 {
412     if (readTask_ != nullptr) {
413         readTask_->Stop();
414     }
415     return 0;
416 }
417 
SetDecoderOutputBufferPts(std::shared_ptr<AVBuffer> & outputBuffer)418 void AVThumbnailGenerator::SetDecoderOutputBufferPts(std::shared_ptr<AVBuffer> &outputBuffer)
419 {
420     CHECK_AND_RETURN_NOLOG(outputBuffer != nullptr);
421     std::unique_lock<std::mutex> lock(dtsQueMutex_);
422     if (!inputBufferDtsQue_.empty()) {
423         outputBuffer->pts_ = inputBufferDtsQue_.front();
424         inputBufferDtsQue_.pop_front();
425         MEDIA_LOGD("DecOutputbuf PTS: %{public}" PRId64 " dtsQue_ size: %{public}" PRIu64,
426             outputBuffer->pts_, static_cast<uint64_t>(inputBufferDtsQue_.size()));
427     } else {
428         MEDIA_LOGW("DtsQue_ is empty. DecOutputbuf DTS: %{public}" PRId64, outputBuffer->dts_);
429         outputBuffer->pts_ = outputBuffer->dts_;
430     }
431 }
432 
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)433 void AVThumbnailGenerator::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
434 {
435     if (fileType_ == FileType::AVI) {
436         SetDecoderOutputBufferPts(buffer);
437     }
438     CHECK_AND_RETURN_LOG(buffer != nullptr, "buffer is nullptr");
439     MEDIA_LOGD("OnOutputBufferAvailable index:%{public}u , pts %{public}" PRId64, index, buffer->pts_);
440     CHECK_AND_RETURN_LOG(videoDecoder_ != nullptr, "Video decoder not exist");
441     bool isEosBuffer = buffer->flag_ & (uint32_t)(AVBufferFlag::EOS);
442     bool isValidBuffer = buffer != nullptr && buffer->memory_ != nullptr &&
443          (buffer->memory_->GetSize() != 0 || buffer->memory_->GetSurfaceBuffer() != nullptr || isEosBuffer);
444     bool isValidState = !hasFetchedFrame_.load() && !stopProcessing_.load();
445     if (!isValidBuffer || !isValidState) {
446         MEDIA_LOGW("isValidBuffer %{public}d isValidState %{public}d", isValidBuffer, isValidState);
447         videoDecoder_->ReleaseOutputBuffer(index, false);
448         return;
449     }
450     bool isClosest = seekMode_ == Plugins::SeekMode::SEEK_CLOSEST;
451     bool isAvailableFrame = !isClosest || buffer->pts_ >= seekTime_ || isEosBuffer;
452     if (!isAvailableFrame) {
453         videoDecoder_->ReleaseOutputBuffer(bufferIndex_, false);
454         bufferIndex_ = index;
455         avBuffer_ = buffer;
456         return;
457     }
458 
459     {
460         std::unique_lock<std::mutex> lock(mutex_);
461         hasFetchedFrame_ = true;
462     }
463     if (isClosest && avBuffer_ != nullptr) {
464         int64_t preDiff = seekTime_ - avBuffer_->pts_;
465         int64_t nextDiff = buffer->pts_ - seekTime_;
466         if (preDiff > nextDiff && !(buffer->flag_ & (uint32_t)(AVBufferFlag::EOS))) {
467             videoDecoder_->ReleaseOutputBuffer(bufferIndex_, false);
468             bufferIndex_ = index;
469             avBuffer_ = buffer;
470         } else {
471             videoDecoder_->ReleaseOutputBuffer(index, false);
472         }
473     } else {
474         bufferIndex_ = index;
475         avBuffer_ = buffer;
476     }
477     MEDIA_LOGI("dstTime %{public}" PRId64 " resTime %{public}" PRId64, seekTime_, buffer->pts_);
478     cond_.notify_all();
479     PauseFetchFrame();
480 }
481 
FetchFrameAtTime(int64_t timeUs,int32_t option,const OutputConfiguration & param)482 std::shared_ptr<AVSharedMemory> AVThumbnailGenerator::FetchFrameAtTime(int64_t timeUs, int32_t option,
483                                                                        const OutputConfiguration &param)
484 {
485     MEDIA_LOGI("Fetch frame 0x%{public}06" PRIXPTR " timeUs:%{public}" PRId64 ", option:%{public}d,"
486                "dstWidth:%{public}d, dstHeight:%{public}d, colorFormat:%{public}d",
487                FAKE_POINTER(this), timeUs, option, param.dstWidth, param.dstHeight,
488                static_cast<int32_t>(param.colorFormat));
489     CHECK_AND_RETURN_RET_LOG(mediaDemuxer_ != nullptr, nullptr, "FetchFrameAtTime demuxer is nullptr");
490 
491     readErrorFlag_ = false;
492     hasFetchedFrame_ = false;
493     isBufferAvailable_ = false;
494     outputConfig_ = param;
495     seekTime_ = timeUs;
496     trackInfo_ = GetVideoTrackInfo();
497     CHECK_AND_RETURN_RET_LOG(trackInfo_ != nullptr, nullptr, "FetchFrameAtTime trackInfo_ is nullptr.");
498     mediaDemuxer_->Resume();
499     mediaDemuxer_->SelectTrack(trackIndex_);
500     int64_t realSeekTime = timeUs;
501     auto res = SeekToTime(Plugins::Us2Ms(timeUs), static_cast<Plugins::SeekMode>(option), realSeekTime);
502     CHECK_AND_RETURN_RET_LOG(res == Status::OK, nullptr, "Seek fail");
503     CHECK_AND_RETURN_RET_LOG(InitDecoder() == Status::OK, nullptr, "FetchFrameAtTime InitDecoder failed.");
504     bool fetchFrameRes = false;
505     {
506         std::unique_lock<std::mutex> lock(mutex_);
507 
508         // wait up to 3s to fetch frame AVSharedMemory at time.
509         fetchFrameRes = cond_.wait_for(lock, std::chrono::seconds(MAX_WAIT_TIME_SECOND),
510             [this] { return hasFetchedFrame_.load() || readErrorFlag_.load() || stopProcessing_.load(); });
511     }
512     if (fetchFrameRes) {
513         HandleFetchFrameAtTimeRes();
514     } else {
515         PauseFetchFrame();
516     }
517     return fetchedFrameAtTime_;
518 }
519 
HandleFetchFrameAtTimeRes()520 void AVThumbnailGenerator::HandleFetchFrameAtTimeRes()
521 {
522     CHECK_AND_RETURN_RET_LOG(!readErrorFlag_.load(), PauseFetchFrame(), "ReadSample error, exit fetchFrame");
523     CHECK_AND_RETURN_RET_LOG(!stopProcessing_.load(), PauseFetchFrame(), "Destroy or Decoder error, exit fetchFrame");
524     MEDIA_LOGI("0x%{public}06" PRIXPTR " Fetch frame OK width:%{public}d, height:%{public}d",
525             FAKE_POINTER(this), outputConfig_.dstWidth, outputConfig_.dstHeight);
526     ConvertToAVSharedMemory();
527     videoDecoder_->ReleaseOutputBuffer(bufferIndex_, false);
528 }
529 
FetchFrameYuv(int64_t timeUs,int32_t option,const OutputConfiguration & param)530 std::shared_ptr<AVBuffer> AVThumbnailGenerator::FetchFrameYuv(int64_t timeUs, int32_t option,
531                                                               const OutputConfiguration &param)
532 {
533     MEDIA_LOGI("Fetch frame 0x%{public}06" PRIXPTR " timeUs:%{public}" PRId64 ", option:%{public}d,"
534                "dstWidth:%{public}d, dstHeight:%{public}d, colorFormat:%{public}d",
535                FAKE_POINTER(this), timeUs, option, param.dstWidth, param.dstHeight,
536                static_cast<int32_t>(param.colorFormat));
537     CHECK_AND_RETURN_RET_LOG(mediaDemuxer_ != nullptr, nullptr, "FetchFrameAtTime demuxer is nullptr");
538     avBuffer_ = nullptr;
539     readErrorFlag_ = false;
540     hasFetchedFrame_ = false;
541     isBufferAvailable_ = false;
542     outputConfig_ = param;
543     seekTime_ = timeUs;
544     trackInfo_ = GetVideoTrackInfo();
545     CHECK_AND_RETURN_RET_LOG(trackInfo_ != nullptr, nullptr, "FetchFrameAtTime trackInfo_ is nullptr.");
546     mediaDemuxer_->SelectTrack(trackIndex_);
547     int64_t realSeekTime = timeUs;
548     auto res = SeekToTime(Plugins::Us2Ms(timeUs), static_cast<Plugins::SeekMode>(option), realSeekTime);
549     CHECK_AND_RETURN_RET_LOG(res == Status::OK, nullptr, "Seek fail");
550     CHECK_AND_RETURN_RET_LOG(InitDecoder() == Status::OK, nullptr, "FetchFrameAtTime InitDecoder failed.");
551     bool fetchFrameRes = false;
552     {
553         std::unique_lock<std::mutex> lock(mutex_);
554 
555         // wait up to 3s to fetch frame AVSharedMemory at time.
556         fetchFrameRes = cond_.wait_for(lock, std::chrono::seconds(MAX_WAIT_TIME_SECOND),
557             [this] { return hasFetchedFrame_.load() || readErrorFlag_.load() || stopProcessing_.load(); });
558     }
559     if (fetchFrameRes) {
560         HandleFetchFrameYuvRes();
561     } else {
562         HandleFetchFrameYuvFailed();
563     }
564     return avBuffer_;
565 }
566 
HandleFetchFrameYuvRes()567 void AVThumbnailGenerator::HandleFetchFrameYuvRes()
568 {
569     CHECK_AND_RETURN_RET_LOG(!readErrorFlag_.load(), HandleFetchFrameYuvFailed(), "ReadSample error, exit fetchFrame");
570     CHECK_AND_RETURN_RET_LOG(!stopProcessing_.load(), HandleFetchFrameYuvFailed(),
571                              "Destroy or Decoder error, exit fetchFrame");
572     MEDIA_LOGI("0x%{public}06" PRIXPTR " Fetch frame OK width:%{public}d, height:%{public}d",
573                 FAKE_POINTER(this), outputConfig_.dstWidth, outputConfig_.dstHeight);
574     avBuffer_ = GenerateAlignmentAvBuffer();
575     if (avBuffer_ != nullptr && avBuffer_->meta_ != nullptr) {
576         avBuffer_->meta_->Set<Tag::VIDEO_WIDTH>(width_);
577         avBuffer_->meta_->Set<Tag::VIDEO_HEIGHT>(height_);
578         avBuffer_->meta_->Set<Tag::VIDEO_ROTATION>(rotation_);
579         avBuffer_->meta_->Set<Tag::VIDEO_ORIENTATION_TYPE>(orientation_);
580     }
581 }
582 
HandleFetchFrameYuvFailed()583 void AVThumbnailGenerator::HandleFetchFrameYuvFailed()
584 {
585     CHECK_AND_RETURN_LOG(videoDecoder_ != nullptr, "videoDecoder_ is nullptr");
586     videoDecoder_->ReleaseOutputBuffer(bufferIndex_, false);
587     PauseFetchFrame();
588 }
589 
SeekToTime(int64_t timeMs,Plugins::SeekMode option,int64_t realSeekTime)590 Status AVThumbnailGenerator::SeekToTime(int64_t timeMs, Plugins::SeekMode option, int64_t realSeekTime)
591 {
592     seekMode_ = option;
593     if (option == Plugins::SeekMode::SEEK_CLOSEST) {
594         option = Plugins::SeekMode::SEEK_PREVIOUS_SYNC;
595     }
596     timeMs = duration_ > 0 ? std::min(timeMs, Plugins::Us2Ms(duration_)) : timeMs;
597     auto res = mediaDemuxer_->SeekTo(timeMs, option, realSeekTime);
598     if (res != Status::OK && option != Plugins::SeekMode::SEEK_CLOSEST_SYNC) {
599         res = mediaDemuxer_->SeekTo(timeMs, Plugins::SeekMode::SEEK_CLOSEST_SYNC, realSeekTime);
600         seekMode_ = Plugins::SeekMode::SEEK_CLOSEST_SYNC;
601     }
602     return res;
603 }
604 
ConvertToAVSharedMemory()605 void AVThumbnailGenerator::ConvertToAVSharedMemory()
606 {
607     auto surfaceBuffer = avBuffer_->memory_->GetSurfaceBuffer();
608     if (surfaceBuffer != nullptr) {
609         auto ret = GetYuvDataAlignStride(surfaceBuffer);
610         CHECK_AND_RETURN_LOG(ret == MSERR_OK, "Copy frame failed");
611         OutputFrame *frame = reinterpret_cast<OutputFrame *>(fetchedFrameAtTime_->GetBase());
612         frame->width_ = surfaceBuffer->GetWidth();
613         frame->height_ = surfaceBuffer->GetHeight();
614         frame->stride_ = frame->width_ * RATE_UV;
615         frame->bytesPerPixel_ = RATE_UV;
616         frame->size_ = frame->width_ * frame->height_ * BYTES_PER_PIXEL_YUV;
617         frame->rotation_ = static_cast<int32_t>(rotation_);
618         return;
619     }
620 
621     int32_t width;
622     int32_t height;
623     outputFormat_.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width);
624     outputFormat_.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height);
625     if (width == 0 || height == 0) {
626         width = width_;
627         height = height_;
628     }
629 
630     fetchedFrameAtTime_ = std::make_shared<AVSharedMemoryBase>(sizeof(OutputFrame) + avBuffer_->memory_->GetSize(),
631         AVSharedMemory::Flags::FLAGS_READ_WRITE, "FetchedFrameMemory");
632     int32_t ret = fetchedFrameAtTime_->Init();
633     CHECK_AND_RETURN_LOG(ret == static_cast<int32_t>(Status::OK), "Create AVSharedmemory failed, ret:%{public}d", ret);
634     OutputFrame *frame = reinterpret_cast<OutputFrame *>(fetchedFrameAtTime_->GetBase());
635     frame->width_ = width;
636     frame->height_ = height;
637     frame->stride_ = width * RATE_UV;
638     frame->bytesPerPixel_ = RATE_UV;
639     frame->size_ = avBuffer_->memory_->GetSize();
640     frame->rotation_ = static_cast<int32_t>(rotation_);
641     fetchedFrameAtTime_->Write(avBuffer_->memory_->GetAddr(), frame->size_, sizeof(OutputFrame));
642 }
643 
ConvertP010ToNV12(const sptr<SurfaceBuffer> & surfaceBuffer,uint8_t * dstNV12,int32_t strideWidth,int32_t strideHeight)644 void AVThumbnailGenerator::ConvertP010ToNV12(const sptr<SurfaceBuffer> &surfaceBuffer, uint8_t *dstNV12,
645                                              int32_t strideWidth, int32_t strideHeight)
646 {
647     int32_t width = surfaceBuffer->GetWidth();
648     int32_t height = surfaceBuffer->GetHeight();
649     uint8_t *srcP010 = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr());
650 
651     // copy src Y component to dst
652     for (int32_t i = 0; i < height; i++) {
653         uint16_t *srcY = reinterpret_cast<uint16_t *>(srcP010 + strideWidth * i);
654         uint8_t *dstY = dstNV12 + width * i;
655         for (int32_t j = 0; j < width; j++) {
656             *dstY = static_cast<uint8_t>(*srcY >> SHIFT_BITS_P010_2_NV12);
657             srcY++;
658             dstY++;
659         }
660     }
661 
662     uint8_t *maxDstAddr = dstNV12 + width * height + width * height / RATE_UV;
663     uint8_t *originSrcAddr = srcP010;
664     uint16_t *maxSrcAddr = reinterpret_cast<uint16_t *>(originSrcAddr) + surfaceBuffer->GetSize();
665 
666     srcP010 = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr()) + strideWidth * strideHeight;
667     dstNV12 = dstNV12 + width * height;
668 
669     // copy src UV component to dst, height(UV) = height(Y) / 2;
670     for (int32_t i = 0; i < height / 2; i++) {
671         uint16_t *srcUV = reinterpret_cast<uint16_t *>(srcP010 + strideWidth * i);
672         uint8_t *dstUV = dstNV12 + width * i;
673         for (int32_t j = 0; j < width && srcUV < maxSrcAddr && dstUV < maxDstAddr; j++) {
674             *dstUV = static_cast<uint8_t>(*srcUV >> SHIFT_BITS_P010_2_NV12);
675             *(dstUV + 1) = static_cast<uint8_t>(*(srcUV + 1) >> SHIFT_BITS_P010_2_NV12);
676             srcUV += 2;  // srcUV move by 2 to process U and V component
677             dstUV += 2;  // dstUV move by 2 to process U and V component
678         }
679     }
680 }
681 
GenerateAlignmentAvBuffer()682 std::shared_ptr<AVBuffer> AVThumbnailGenerator::GenerateAlignmentAvBuffer()
683 {
684     CHECK_AND_RETURN_RET_LOG(avBuffer_ != nullptr && avBuffer_->memory_ != nullptr, nullptr,
685         "Generate Alignment AvBuffer failed, avBuffer_ or avBuffer_->memory_ is nullptr.");
686     if (avBuffer_->memory_->GetSize() != 0 && avBuffer_->memory_->GetSurfaceBuffer() == nullptr) {
687         return GenerateAvBufferFromFCodec();
688     }
689     CHECK_AND_RETURN_RET_LOG(avBuffer_->memory_->GetSurfaceBuffer() != nullptr, nullptr,
690         "Memory size is 0, SurfaceBuffer is nullptr.");
691     auto srcSurfaceBuffer = avBuffer_->memory_->GetSurfaceBuffer();
692     auto width = srcSurfaceBuffer->GetWidth();
693     auto height = srcSurfaceBuffer->GetHeight();
694     bool isHdr = srcSurfaceBuffer->GetFormat() ==
695                  static_cast<int32_t>(GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_P010);
696 
697     sptr<SurfaceBuffer> dstSurfaceBuffer = SurfaceBuffer::Create();
698     BufferRequestConfig requestConfig = {
699         .width = width,
700         .height = height,
701         .strideAlignment = 0x2,
702         .format = srcSurfaceBuffer->GetFormat(),  // always yuv
703         .usage = srcSurfaceBuffer->GetUsage(),
704         .timeout = 0,
705     };
706     CHECK_AND_RETURN_RET_LOG(dstSurfaceBuffer != nullptr, nullptr, "Create surfaceBuffer failed");
707     GSError allocRes = dstSurfaceBuffer->Alloc(requestConfig);
708     CHECK_AND_RETURN_RET_LOG(allocRes == 0, nullptr, "Alloc surfaceBuffer failed, ecode %{public}d", allocRes);
709 
710     CopySurfaceBufferInfo(srcSurfaceBuffer, dstSurfaceBuffer);
711     int32_t copyRes = memcpy_s(dstSurfaceBuffer->GetVirAddr(), dstSurfaceBuffer->GetSize(),
712                                srcSurfaceBuffer->GetVirAddr(), srcSurfaceBuffer->GetSize());
713     CHECK_AND_RETURN_RET_LOG(copyRes == EOK, nullptr, "copy surface buffer pixels failed, copyRes %{public}d", copyRes);
714     int32_t outputHeight;
715     auto hasSliceHeight = outputFormat_.GetIntValue(Tag::VIDEO_SLICE_HEIGHT, outputHeight);
716     if (!hasSliceHeight || outputHeight < height) {
717         outputHeight = height;
718     }
719 
720     // create avBuffer from surfaceBuffer
721     std::shared_ptr<AVBuffer> targetAvBuffer = AVBuffer::CreateAVBuffer(dstSurfaceBuffer);
722     bool ret = targetAvBuffer && targetAvBuffer->memory_ && targetAvBuffer->meta_ &&
723                targetAvBuffer->memory_->GetSurfaceBuffer() != nullptr;
724     CHECK_AND_RETURN_RET_LOG(ret, nullptr, "create avBuffer failed");
725     targetAvBuffer->meta_->Set<Tag::VIDEO_IS_HDR_VIVID>(isHdr);
726     targetAvBuffer->meta_->Set<Tag::VIDEO_SLICE_HEIGHT>(outputHeight);
727     targetAvBuffer->flag_ = avBuffer_->flag_;
728     return targetAvBuffer;
729 }
730 
GenerateAvBufferFromFCodec()731 std::shared_ptr<AVBuffer> AVThumbnailGenerator::GenerateAvBufferFromFCodec()
732 {
733     AVBufferConfig avBufferConfig;
734     avBufferConfig.size = avBuffer_->memory_->GetSize();
735     avBufferConfig.memoryType = MemoryType::SHARED_MEMORY;
736     avBufferConfig.memoryFlag = MemoryFlag::MEMORY_READ_WRITE;
737     std::shared_ptr<AVBuffer> targetAvBuffer = AVBuffer::CreateAVBuffer(avBufferConfig);
738     CHECK_AND_RETURN_RET_LOG(targetAvBuffer != nullptr && targetAvBuffer->memory_ != nullptr, nullptr,
739         "Create avBuffer failed");
740     targetAvBuffer->memory_->Write(avBuffer_->memory_->GetAddr(), avBuffer_->memory_->GetSize(), 0);
741     return targetAvBuffer;
742 }
743 
GetYuvDataAlignStride(const sptr<SurfaceBuffer> & surfaceBuffer)744 int32_t AVThumbnailGenerator::GetYuvDataAlignStride(const sptr<SurfaceBuffer> &surfaceBuffer)
745 {
746     int32_t width = surfaceBuffer->GetWidth();
747     int32_t height = surfaceBuffer->GetHeight();
748     int32_t stride = surfaceBuffer->GetStride();
749     int32_t outputHeight;
750     auto hasSliceHeight = outputFormat_.GetIntValue(Tag::VIDEO_SLICE_HEIGHT, outputHeight);
751     if (!hasSliceHeight || outputHeight < height) {
752         outputHeight = height;
753     }
754     MEDIA_LOGD("GetYuvDataAlignStride stride:%{public}d, strideWidth:%{public}d, outputHeight:%{public}d", stride,
755                stride, outputHeight);
756 
757     fetchedFrameAtTime_ =
758         std::make_shared<AVSharedMemoryBase>(sizeof(OutputFrame) + width * height * BYTES_PER_PIXEL_YUV,
759             AVSharedMemory::Flags::FLAGS_READ_WRITE, "FetchedFrameMemory");
760     auto ret = fetchedFrameAtTime_->Init();
761     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Create AVSharedmemory failed, ret:%{public}d", ret);
762     uint8_t *dstPtr = static_cast<uint8_t *>(sizeof(OutputFrame) + fetchedFrameAtTime_->GetBase());
763     uint8_t *srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr());
764     int32_t format = surfaceBuffer->GetFormat();
765     if (format == static_cast<int32_t>(GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_P010)) {
766         ConvertP010ToNV12(surfaceBuffer, dstPtr, stride, outputHeight);
767         return MSERR_OK;
768     }
769 
770     // copy src Y component to dst
771     for (int32_t y = 0; y < height; y++) {
772         auto ret = memcpy_s(dstPtr, width, srcPtr, width);
773         if (ret != EOK) {
774             MEDIA_LOGW("Memcpy Y component failed.");
775         }
776         srcPtr += stride;
777         dstPtr += width;
778     }
779 
780     srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr()) + stride * outputHeight;
781 
782     // copy src UV component to dst, height(UV) = height(Y) / 2
783     for (int32_t uv = 0; uv < height / 2; uv++) {
784         auto ret = memcpy_s(dstPtr, width, srcPtr, width);
785         if (ret != EOK) {
786             MEDIA_LOGW("Memcpy UV component failed.");
787         }
788         srcPtr += stride;
789         dstPtr += width;
790     }
791     return MSERR_OK;
792 }
793 
Reset()794 void AVThumbnailGenerator::Reset()
795 {
796     if (mediaDemuxer_ != nullptr) {
797         mediaDemuxer_->Reset();
798     }
799 
800     if (videoDecoder_ != nullptr) {
801         videoDecoder_->Reset();
802     }
803 
804     FlushBufferQueue();
805 
806     hasFetchedFrame_ = false;
807     fileType_ = FileType::UNKNOW;
808     trackInfo_ = nullptr;
809 }
810 
FlushBufferQueue()811 void AVThumbnailGenerator::FlushBufferQueue()
812 {
813     {
814         std::unique_lock<std::mutex> lock(queueMutex_);
815         if (inputBufferQueueConsumer_ != nullptr) {
816             for (auto &buffer : bufferVector_) {
817                 inputBufferQueueConsumer_->DetachBuffer(buffer);
818             }
819             bufferVector_.clear();
820             inputBufferQueueConsumer_->SetQueueSize(0);
821         }
822         isBufferAvailable_ = false;
823     }
824     {
825         std::unique_lock<std::mutex> lock(dtsQueMutex_);
826         if (!inputBufferDtsQue_.empty()) {
827             MEDIA_LOGI("Clear dtsQue_, currrent size: %{public}" PRIu64,
828                 static_cast<uint64_t>(inputBufferDtsQue_.size()));
829             inputBufferDtsQue_.clear();
830         }
831     }
832 }
833 
CopySurfaceBufferInfo(sptr<SurfaceBuffer> & source,sptr<SurfaceBuffer> & dst)834 void AVThumbnailGenerator::CopySurfaceBufferInfo(sptr<SurfaceBuffer> &source, sptr<SurfaceBuffer> &dst)
835 {
836     if (source == nullptr || dst == nullptr) {
837         MEDIA_LOGI("CopySurfaceBufferInfo failed, source or dst is nullptr");
838         return;
839     }
840     std::vector<uint8_t> hdrMetadataTypeVec;
841     std::vector<uint8_t> colorSpaceInfoVec;
842     std::vector<uint8_t> staticData;
843     std::vector<uint8_t> dynamicData;
844 
845     if (source->GetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec) == GSERROR_OK) {
846         dst->SetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec);
847     }
848     if (source->GetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec) == GSERROR_OK) {
849         dst->SetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec);
850     }
851     if (GetSbStaticMetadata(source, staticData) && (staticData.size() > 0)) {
852         SetSbStaticMetadata(dst, staticData);
853     }
854     if (GetSbDynamicMetadata(source, dynamicData) && (dynamicData.size()) > 0) {
855         SetSbDynamicMetadata(dst, dynamicData);
856     }
857 }
858 
GetSbStaticMetadata(const sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & staticMetadata)859 bool AVThumbnailGenerator::GetSbStaticMetadata(const sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &staticMetadata)
860 {
861     return buffer->GetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
862 }
863 
GetSbDynamicMetadata(const sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & dynamicMetadata)864 bool AVThumbnailGenerator::GetSbDynamicMetadata(const sptr<SurfaceBuffer> &buffer,
865                                                 std::vector<uint8_t> &dynamicMetadata)
866 {
867     return buffer->GetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
868 }
869 
SetSbStaticMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & staticMetadata)870 bool AVThumbnailGenerator::SetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, const std::vector<uint8_t> &staticMetadata)
871 {
872     return buffer->SetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
873 }
874 
SetSbDynamicMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & dynamicMetadata)875 bool AVThumbnailGenerator::SetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer,
876                                                 const std::vector<uint8_t> &dynamicMetadata)
877 {
878     return buffer->SetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
879 }
880 
Destroy()881 void AVThumbnailGenerator::Destroy()
882 {
883     {
884         std::unique_lock<std::mutex> lock(queueMutex_);
885         stopProcessing_ = true;
886     }
887     bufferAvailableCond_.notify_all();
888 
889     if (readTask_ != nullptr) {
890         readTask_->Stop();
891     }
892 
893     if (videoDecoder_ != nullptr) {
894         videoDecoder_->Stop();
895         videoDecoder_->Release();
896     }
897     mediaDemuxer_ = nullptr;
898     videoDecoder_ = nullptr;
899     MEDIA_LOGI("0x%{public}06" PRIXPTR " Finish Destroy.", FAKE_POINTER(this));
900 }
901 
PauseFetchFrame()902 void AVThumbnailGenerator::PauseFetchFrame()
903 {
904     hasFetchedFrame_ = true;
905     mediaDemuxer_->Pause();
906     mediaDemuxer_->Flush();
907     videoDecoder_->Flush();
908     Format format;
909     format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate_);
910     videoDecoder_->SetParameter(format);
911     FlushBufferQueue();
912 }
913 }  // namespace Media
914 }  // namespace OHOS