• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/codec/SkCodec.h"
9 #include "include/core/SkData.h"
10 #include "include/core/SkImage.h"
11 #include "include/utils/SkAnimCodecPlayer.h"
12 #include "src/codec/SkCodecImageGenerator.h"
13 #include <algorithm>
14 
SkAnimCodecPlayer(std::unique_ptr<SkCodec> codec)15 SkAnimCodecPlayer::SkAnimCodecPlayer(std::unique_ptr<SkCodec> codec) : fCodec(std::move(codec)) {
16     fImageInfo = fCodec->getInfo();
17     fFrameInfos = fCodec->getFrameInfo();
18     fImages.resize(fFrameInfos.size());
19 
20     // change the interpretation of fDuration to a end-time for that frame
21     size_t dur = 0;
22     for (auto& f : fFrameInfos) {
23         dur += f.fDuration;
24         f.fDuration = dur;
25     }
26     fTotalDuration = dur;
27 
28     if (!fTotalDuration) {
29         // Static image -- may or may not have returned a single frame info.
30         fFrameInfos.clear();
31         fImages.clear();
32         fImages.push_back(SkImage::MakeFromGenerator(
33                               SkCodecImageGenerator::MakeFromCodec(std::move(fCodec))));
34     }
35 }
36 
~SkAnimCodecPlayer()37 SkAnimCodecPlayer::~SkAnimCodecPlayer() {}
38 
dimensions()39 SkISize SkAnimCodecPlayer::dimensions() {
40     return { fImageInfo.width(), fImageInfo.height() };
41 }
42 
getFrameAt(int index)43 sk_sp<SkImage> SkAnimCodecPlayer::getFrameAt(int index) {
44     SkASSERT((unsigned)index < fFrameInfos.size());
45 
46     if (fImages[index]) {
47         return fImages[index];
48     }
49 
50     size_t rb = fImageInfo.minRowBytes();
51     size_t size = fImageInfo.computeByteSize(rb);
52     auto data = SkData::MakeUninitialized(size);
53 
54     SkCodec::Options opts;
55     opts.fFrameIndex = index;
56 
57     const int requiredFrame = fFrameInfos[index].fRequiredFrame;
58     if (requiredFrame != SkCodec::kNoFrame) {
59         auto requiredImage = fImages[requiredFrame];
60         SkPixmap requiredPM;
61         if (requiredImage && requiredImage->peekPixels(&requiredPM)) {
62             sk_careful_memcpy(data->writable_data(), requiredPM.addr(), size);
63             opts.fPriorFrame = requiredFrame;
64         }
65     }
66     if (SkCodec::kSuccess == fCodec->getPixels(fImageInfo, data->writable_data(), rb, &opts)) {
67         return fImages[index] = SkImage::MakeRasterData(fImageInfo, std::move(data), rb);
68     }
69     return nullptr;
70 }
71 
getFrame()72 sk_sp<SkImage> SkAnimCodecPlayer::getFrame() {
73     SkASSERT(fTotalDuration > 0 || fImages.size() == 1);
74 
75     return fTotalDuration > 0
76         ? this->getFrameAt(fCurrIndex)
77         : fImages.front();
78 }
79 
seek(uint32_t msec)80 bool SkAnimCodecPlayer::seek(uint32_t msec) {
81     if (!fTotalDuration) {
82         return false;
83     }
84 
85     msec %= fTotalDuration;
86 
87     auto lower = std::lower_bound(fFrameInfos.begin(), fFrameInfos.end(), msec,
88                                   [](const SkCodec::FrameInfo& info, uint32_t msec) {
89                                       return (uint32_t)info.fDuration < msec;
90                                   });
91     int prevIndex = fCurrIndex;
92     fCurrIndex = lower - fFrameInfos.begin();
93     return fCurrIndex != prevIndex;
94 }
95 
96 
97