Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions | Variables
SkottieTool.cpp File Reference
#include "include/codec/SkCodec.h"
#include "include/codec/SkJpegDecoder.h"
#include "include/codec/SkPngDecoder.h"
#include "include/codec/SkWebpDecoder.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/encode/SkPngEncoder.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTo.h"
#include "modules/skottie/include/ExternalLayer.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "modules/skresources/include/SkResources.h"
#include "modules/skshaper/utils/FactoryHelpers.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkTaskGroup.h"
#include "src/utils/SkOSPath.h"
#include "tools/flags/CommandLineFlags.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "tools/gpu/ContextType.h"
#include "tools/gpu/GrContextFactory.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSerialProcs.h"
#include "src/image/SkImage_Base.h"
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <cstring>
#include <functional>
#include <memory>
#include <numeric>
#include <utility>
#include <vector>
#include "include/ports/SkFontMgr_empty.h"

Go to the source code of this file.

Functions

static DEFINE_string2 (input, i, nullptr, "Input .json file.")
 
static DEFINE_string2 (writePath, w, nullptr, "Output directory. Frames are names [0-9]{6}.png.")
 
static DEFINE_string2 (format, f, "png", formats_help)
 
static DEFINE_double (t0, 0, "Timeline start [0..1].")
 
static DEFINE_double (t1, 1, "Timeline stop [0..1].")
 
static DEFINE_double (fps, 0, "Decode frames per second (default is animation native fps).")
 
static DEFINE_int (width, 800, "Render width.")
 
static DEFINE_int (height, 600, "Render height.")
 
static DEFINE_int (threads, 0, "Number of worker threads (0 -> cores count).")
 
static DEFINE_bool2 (gpu, g, false, "Enable GPU rasterization.")
 
int main (int argc, char **argv)
 

Variables

const char * formats_help = "Output format (png, skp, or null)"
 
bool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental
 

Function Documentation

◆ DEFINE_bool2()

static DEFINE_bool2 ( gpu  ,
,
false  ,
"Enable GPU rasterization."   
)
static

◆ DEFINE_double() [1/3]

static DEFINE_double ( fps  ,
,
"Decode frames per second (default is animation native fps)."   
)
static

◆ DEFINE_double() [2/3]

static DEFINE_double ( t0  ,
,
"Timeline start ."  [0..1] 
)
static

◆ DEFINE_double() [3/3]

static DEFINE_double ( t1  ,
,
"Timeline stop ."  [0..1] 
)
static

◆ DEFINE_int() [1/3]

static DEFINE_int ( height  ,
600  ,
"Render height."   
)
static

◆ DEFINE_int() [2/3]

static DEFINE_int ( threads  ,
,
"Number of worker threads (0 -> cores count)."   
)
static

◆ DEFINE_int() [3/3]

static DEFINE_int ( width  ,
800  ,
"Render width."   
)
static

◆ DEFINE_string2() [1/3]

static DEFINE_string2 ( format  ,
,
"png"  ,
formats_help   
)
static

◆ DEFINE_string2() [2/3]

static DEFINE_string2 ( input  ,
,
nullptr  ,
"Input .json file."   
)
static

◆ DEFINE_string2() [3/3]

static DEFINE_string2 ( writePath  ,
w  ,
nullptr  ,
"Output directory. Frames are names {6}.png."  [0-9] 
)
static

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 472 of file SkottieTool.cpp.

472 {
474 CommandLineFlags::Parse(argc, argv);
476
477 if (FLAGS_input.isEmpty() || FLAGS_writePath.isEmpty()) {
478 SkDebugf("Missing required 'input' and 'writePath' args.\n");
479 return 1;
480 }
481
482 OutputFormat fmt;
483 if (0 == std::strcmp(FLAGS_format[0], "png")) {
484 fmt = OutputFormat::kPNG;
485 } else if (0 == std::strcmp(FLAGS_format[0], "skp")) {
486 fmt = OutputFormat::kSKP;
487 } else if (0 == std::strcmp(FLAGS_format[0], "null")) {
488 fmt = OutputFormat::kNull;
489#if defined(HAVE_VIDEO_ENCODER)
490 } else if (0 == std::strcmp(FLAGS_format[0], "mp4")) {
491 fmt = OutputFormat::kMP4;
492#endif
493 } else {
494 fprintf(stderr, "Unknown format: %s\n", FLAGS_format[0]);
495 return 1;
496 }
497
498 if (fmt != OutputFormat::kMP4 && !sk_mkdir(FLAGS_writePath[0])) {
499 return 1;
500 }
501
502 SkCodecs::Register(SkPngDecoder::Decoder());
503 SkCodecs::Register(SkJpegDecoder::Decoder());
504 SkCodecs::Register(SkWebpDecoder::Decoder());
505
506 // If necessary, clients should use a font manager that would load fonts from the system.
507#if defined(SK_BUILD_FOR_MAC) && defined(SK_FONTMGR_CORETEXT_AVAILABLE)
509#elif defined(SK_BUILD_FOR_ANDROID) && defined(SK_FONTMGR_ANDROID_AVAILABLE)
510 sk_sp<SkFontMgr> fontMgr = SkFontMgr_New_Android(nullptr, std::make_unique<SkFontScanner_FreeType>());
511#elif defined(SK_BUILD_FOR_UNIX) && defined(SK_FONTMGR_FONTCONFIG_AVAILABLE)
513#else
515#endif
516
518 auto logger = sk_make_sp<Logger>();
522 predecode),
523 predecode,
524 fontMgr));
525 auto data = SkData::MakeFromFileName(FLAGS_input[0]);
526 auto precomp_interceptor =
527 sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(rp, "__");
528
529 if (!data) {
530 SkDebugf("Could not load %s.\n", FLAGS_input[0]);
531 return 1;
532 }
533
534 // Instantiate an animation on the main thread for two reasons:
535 // - we need to know its duration upfront
536 // - we want to only report parsing errors once
537 auto anim = skottie::Animation::Builder()
539 .setLogger(logger)
542 .make(static_cast<const char*>(data->data()), data->size());
543 if (!anim) {
544 SkDebugf("Could not parse animation: '%s'.\n", FLAGS_input[0]);
545 return 1;
546 }
547
548 const auto scale_matrix = SkMatrix::RectToRect(SkRect::MakeSize(anim->size()),
549 SkRect::MakeIWH(FLAGS_width, FLAGS_height),
551 logger->report();
552
553 const auto t0 = SkTPin(FLAGS_t0, 0.0, 1.0),
554 t1 = SkTPin(FLAGS_t1, t0, 1.0),
555 native_fps = anim->fps(),
556 frame0 = anim->duration() * t0 * native_fps,
557 duration = anim->duration() * (t1 - t0);
558
559 double fps = FLAGS_fps > 0 ? FLAGS_fps : native_fps;
560 if (fps <= 0) {
561 SkDebugf("Invalid fps: %f.\n", fps);
562 return 1;
563 }
564
565 auto frame_count = static_cast<int>(duration * fps);
566 static constexpr int kMaxFrames = 10000;
567 if (frame_count > kMaxFrames) {
568 frame_count = kMaxFrames;
569 fps = frame_count / duration;
570 }
571 const auto fps_scale = native_fps / fps;
572
573 printf("Rendering %f seconds (%d frames @%f fps).\n", duration, frame_count, fps);
574
575 const auto sink = FrameSink::Make(fmt, frame_count);
576
577 std::vector<double> frames_ms(frame_count);
578
579 const auto thread_count = FLAGS_gpu ? 0 : FLAGS_threads - 1;
580 SkTaskGroup::Enabler enabler(thread_count);
581
582 SkTaskGroup tg;
583 {
584 // Depending on type (gpu vs. everything else), we use either a single generator
585 // or one generator per worker thread, respectively.
586 // Scoping is important for the single generator case because we want its destructor to
587 // flush out any pending async operations.
588 std::unique_ptr<FrameGenerator> singleton_generator;
589 if (FLAGS_gpu) {
590 singleton_generator = FrameGenerator::Make(sink.get(), fmt, scale_matrix);
591 }
592
593 tg.batch(frame_count, [&](int i) {
594 // SkTaskGroup::Enabler creates a LIFO work pool,
595 // but we want our early frames to start first.
596 i = frame_count - 1 - i;
597
598 const auto start = std::chrono::steady_clock::now();
599 thread_local static auto* anim =
602 .setPrecompInterceptor(precomp_interceptor)
603 .make(static_cast<const char*>(data->data()), data->size())
604 .release();
605 thread_local static auto* gen = singleton_generator
606 ? singleton_generator.get()
607 : FrameGenerator::Make(sink.get(), fmt, scale_matrix).release();
608
609 if (gen && anim) {
610 anim->seekFrame(frame0 + i * fps_scale);
611 gen->generateFrame(anim, SkToSizeT(i));
612 } else {
613 sink->writeFrame(nullptr, SkToSizeT(i));
614 }
615
616 frames_ms[i] = ms_since(start);
617 });
618 }
619
620 sink->finalize(fps);
621 tg.wait();
622
623
624 std::sort(frames_ms.begin(), frames_ms.end());
625 double sum = std::accumulate(frames_ms.begin(), frames_ms.end(), 0);
626 printf("Frame time stats: min %gms, med %gms, avg %gms, max %gms, sum %gms\n",
627 frames_ms[0], frames_ms[frame_count/2], sum/frame_count, frames_ms.back(), sum);
628
629 return 0;
630}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts *custom)
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Custom_Empty()
SK_API sk_sp< SkFontMgr > SkFontMgr_New_FontConfig(FcConfig *fc)
SK_API sk_sp< SkFontMgr > SkFontMgr_New_CoreText(CTFontCollectionRef)
bool sk_mkdir(const char *path)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
constexpr size_t SkToSizeT(S x)
Definition SkTo.h:31
bool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental
static void Parse(int argc, const char *const *argv)
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition SkData.cpp:148
static void Init()
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition SkMatrix.h:157
@ kCenter_ScaleToFit
scales and aligns to center
Definition SkMatrix.h:139
static SkString Dirname(const char *fullPath)
Definition SkOSPath.cpp:36
void batch(int N, std::function< void(int)> fn)
Builder & setResourceProvider(sk_sp< ResourceProvider >)
Definition Skottie.cpp:309
Builder & setFontManager(sk_sp< SkFontMgr >)
Definition Skottie.cpp:314
Builder & setPrecompInterceptor(sk_sp< PrecompInterceptor >)
Definition Skottie.cpp:334
Builder & setLogger(sk_sp< Logger >)
Definition Skottie.cpp:324
sk_sp< Animation > make(SkStream *)
Definition Skottie.cpp:349
Builder & setTextShapingFactory(sk_sp< SkShapers::Factory >)
Definition Skottie.cpp:344
static sk_sp< CachingResourceProvider > Make(sk_sp< ResourceProvider > rp)
static sk_sp< DataURIResourceProviderProxy > Make(sk_sp< ResourceProvider > rp, ImageDecodeStrategy=ImageDecodeStrategy::kLazyDecode, sk_sp< const SkFontMgr > fontMgr=nullptr)
static sk_sp< FileResourceProvider > Make(SkString base_dir, ImageDecodeStrategy=ImageDecodeStrategy::kLazyDecode)
sk_sp< SkFontMgr > fontMgr
Definition examples.cpp:32
double duration
Definition examples.cpp:30
constexpr SkCodecs::Decoder Decoder()
constexpr SkCodecs::Decoder Decoder()
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
sk_sp< Factory > BestAvailable()
constexpr SkCodecs::Decoder Decoder()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
Definition gen.py:1
static SkString fmt(SkColor4f c)
Definition p3.cpp:43
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623
static constexpr SkRect MakeSize(const SkSize &size)
Definition SkRect.h:633

Variable Documentation

◆ formats_help

const char* formats_help = "Output format (png, skp, or null)"

Definition at line 72 of file SkottieTool.cpp.

◆ gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental

bool gSkUseThreadLocalStrikeCaches_IAcknowledgeThisIsIncrediblyExperimental
extern

Definition at line 28 of file SkStrikeCache.cpp.