Skia is slow to get frame images. How to render gif animation

281 views
Skip to first unread message

刘晓伦

unread,
Mar 18, 2023, 9:38:48 AM3/18/23
to skia-discuss
This is a part of my code.
The codec->getImage method is slow.
It take more than 100 milliseconds  (more than fDuration time).
This makes my gif animation look slow.
I know  codec->getImage  requires copying frame data.
But If I copy the frame data into memory before rendering.
A gif of around 3M consumes 1G of memory.
Is there a way to play gif smoothly without consuming too much memory and CPU resources? Just like Google Chrome.
What should I do?
Thanks very much.

```c++
auto skData = SkData::MakeFromFileName(path.c_str());
std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(skData);
auto imageInfo = codec->getInfo();
auto frameCount = codec->getFrameCount();
SkCodec::Options option;
auto frameInfo = codec->getFrameInfo();
while (running)
{            
    option.fFrameIndex = currentFrameIndex;
    auto result = codec->getImage(imageInfo, &option);
    currentFrameImage = std::get<0>(result);
    auto span = frameInfo[currentFrameIndex].fDuration;
    std::this_thread::sleep_for(std::chrono::milliseconds(span));
    if (currentFrameIndex >= frameCount-1)
    {
        currentFrameIndex = 0;
    }
    else
    {
        currentFrameIndex += 1;
    }
}
```

Brian Osman

unread,
Mar 18, 2023, 9:41:00 AM3/18/23
to skia-d...@googlegroups.com
What kind of hardware are you running on (100 ms seems like a very long time to decode a single frame). Are you running in release mode (with optimizations enabled?) or in debug mode?

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/1dc1cc90-0ed2-4a54-b098-8d76eed24009n%40googlegroups.com.

刘晓伦

unread,
Mar 19, 2023, 10:01:58 AM3/19/23
to skia-discuss
Thanks for your reply.
This is a mistake that I didn't make good use of  `fPriorFrame`
The correct code should be:
```c++
decodeThread = std::thread([this](std::unique_ptr<SkCodec> codec){      
    auto frameCount = codec->getFrameCount();
    SkCodec::Options option;
    option.fFrameIndex = 0;
    option.fPriorFrame = -1;
    auto imageInfo = codec->getInfo().makeColorType(kN32_SkColorType);

    auto frameInfo = codec->getFrameInfo();
    while (running)
    {
        auto start = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();            
        std::shared_ptr<SkBitmap> image = std::make_shared<SkBitmap>();
        image->allocPixels(imageInfo);
        if (option.fFrameIndex != 0)
        {
            copy_to(image.get(), frameImage->colorType(), *frameImage.get());
        }
        codec->getPixels(imageInfo, image->getPixels(), image->rowBytes(), &option);
        std::unique_lock guard(locker);
        frameImage = image;
        guard.unlock();
        App::get()->mainWindow->Refresh();
        auto end = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
        auto span = frameInfo[option.fFrameIndex].fDuration - (end - start);

        std::this_thread::sleep_for(std::chrono::milliseconds(span));
        if (option.fFrameIndex == frameCount - 1)
        {
            option.fPriorFrame = -1;
            option.fFrameIndex = 0;
        }
        else
        {
            option.fPriorFrame = option.fPriorFrame + 1;
            option.fFrameIndex = option.fFrameIndex + 1;
        }            
    }
},std::move(codec));
```
Reply all
Reply to author
Forward
0 new messages