blob: 0a9bbc0171ca9fe4e9e86c0c83627041697d05eb [file] [log] [blame]
Mike Reed964aedb2018-10-03 10:16:55 -04001/*
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 "SkAnimCodecPlayer.h"
9#include "SkCodec.h"
10#include "SkData.h"
11#include "SkImage.h"
12#include <algorithm>
13
14SkAnimCodecPlayer::SkAnimCodecPlayer(std::unique_ptr<SkCodec> codec) : fCodec(std::move(codec)) {
15 fImageInfo = fCodec->getInfo();
16 fFrameInfos = fCodec->getFrameInfo();
17 fImages.resize(fFrameInfos.size());
18
19 // change the interpretation of fDuration to a end-time for that frame
20 size_t dur = 0;
21 for (auto& f : fFrameInfos) {
22 dur += f.fDuration;
23 f.fDuration = dur;
24 }
25 fTotalDuration = dur;
26}
27
28SkAnimCodecPlayer::~SkAnimCodecPlayer() {}
29
30SkISize SkAnimCodecPlayer::dimensions() {
31 return { fImageInfo.width(), fImageInfo.height() };
32}
33
34sk_sp<SkImage> SkAnimCodecPlayer::getFrameAt(int index) {
35 SkASSERT((unsigned)index < fFrameInfos.size());
36
37 if (fImages[index]) {
38 return fImages[index];
39 }
40
41 size_t rb = fImageInfo.minRowBytes();
42 size_t size = fImageInfo.computeByteSize(rb);
43 auto data = SkData::MakeUninitialized(size);
44
45 SkCodec::Options opts;
46 opts.fFrameIndex = index;
47
48 const int requiredFrame = fFrameInfos[index].fRequiredFrame;
49 if (requiredFrame != SkCodec::kNoFrame) {
50 auto requiredImage = fImages[requiredFrame];
51 SkPixmap requiredPM;
52 if (requiredImage && requiredImage->peekPixels(&requiredPM)) {
53 sk_careful_memcpy(data->writable_data(), requiredPM.addr(), size);
54 opts.fPriorFrame = requiredFrame;
55 }
56 }
57 if (SkCodec::kSuccess == fCodec->getPixels(fImageInfo, data->writable_data(), rb, &opts)) {
58 return fImages[index] = SkImage::MakeRasterData(fImageInfo, std::move(data), rb);
59 }
60 return nullptr;
61}
62
63sk_sp<SkImage> SkAnimCodecPlayer::getFrame() {
64 return this->getFrameAt(fCurrIndex);
65}
66
67bool SkAnimCodecPlayer::seek(uint32_t msec) {
68 msec %= fTotalDuration;
69
70 auto lower = std::lower_bound(fFrameInfos.begin(), fFrameInfos.end(), msec,
71 [](const SkCodec::FrameInfo& info, uint32_t msec) {
72 return (uint32_t)info.fDuration < msec;
73 });
74 int prevIndex = fCurrIndex;
75 fCurrIndex = lower - fFrameInfos.begin();
76 return fCurrIndex != prevIndex;
77}
78
79