SkAnimCodecPlayer.cpp 2.9 KB

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