Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit 7c2e0ce

Browse files
author
Yuncong Zhang
committed
Fix gif memory problem.
1 parent b87a6b3 commit 7c2e0ce

File tree

2 files changed

+47
-69
lines changed

2 files changed

+47
-69
lines changed

Runtime/ui/painting/GifDecoder.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,11 @@ void _readHeader() {
558558
this._gct = this._readColorTable(this._gctSize);
559559
this._bgColor = this._gct[this._bgIndex];
560560
}
561+
562+
this._currentFrame = new GifFrame {
563+
bytes = new byte[this._width * this._height * sizeof(int)],
564+
delay = 0
565+
};
561566
}
562567

563568
/**
@@ -617,8 +622,8 @@ void _readImage() {
617622
this._setPixels(); // transfer pixel data to image
618623

619624
var bytes = new byte[this._width * this._height * sizeof(int)];
620-
Buffer.BlockCopy(this._image, 0, bytes, 0, bytes.Length);
621-
this._currentFrame = new GifFrame {bytes = bytes, delay = this._delay};
625+
Buffer.BlockCopy(this._image, 0, this._currentFrame.bytes, 0, this._currentFrame.bytes.Length);
626+
this._currentFrame.delay = this._delay;
622627
this._frameCount++;
623628

624629
if (this._transparency) {

Runtime/ui/painting/codec_gif.cs

Lines changed: 40 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Collections;
3-
using System.Collections.Generic;
43
using System.IO;
54
using RSG;
6-
using Unity.UIWidgets.async;
75
using Unity.UIWidgets.foundation;
86
using UnityEngine;
97

@@ -18,34 +16,48 @@ public class FrameData {
1816
public GifDecoder.GifFrame gifFrame;
1917
}
2018

21-
readonly List<Promise<FrameData>> _frames;
19+
volatile byte[] _bytes;
2220
volatile int _width;
2321
volatile int _height;
2422
volatile int _frameCount;
2523
volatile int _repetitionCount;
2624
volatile bool _isDone;
2725
volatile int _frameIndex;
2826
volatile Texture2D _texture;
29-
readonly UIWidgetsCoroutine _coroutine;
27+
volatile FrameData _frameData;
28+
volatile Image _image;
29+
IEnumerator _coroutine;
3030

3131
public GifCodec(byte[] bytes) {
3232
D.assert(bytes != null);
3333
D.assert(isGif(bytes));
3434

35-
this._frames = new List<Promise<FrameData>>();
36-
this._width = 0;
37-
this._height = 0;
3835
this._frameCount = 0;
3936
this._repetitionCount = 0;
4037
this._isDone = false;
4138
this._frameIndex = 0;
39+
this._bytes = bytes;
40+
this._coroutine = this._startDecoding();
41+
this._init();
42+
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false);
43+
this._texture.hideFlags = HideFlags.HideAndDontSave;
44+
this._image = new Image(this._texture);
45+
}
46+
47+
void _init() {
48+
var bytesStream = new MemoryStream(this._bytes);
4249

43-
this._coroutine = Window.instance.startBackgroundCoroutine(
44-
this._startDecoding(bytes, Window.instance));
50+
var gifDecoder = new GifDecoder();
51+
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) {
52+
throw new Exception("Failed to decode gif.");
53+
}
54+
55+
this._width = gifDecoder.frameWidth;
56+
this._height = gifDecoder.frameHeight;
4557
}
4658

47-
IEnumerator _startDecoding(byte[] bytes, Window window) {
48-
var bytesStream = new MemoryStream(bytes);
59+
IEnumerator _startDecoding() {
60+
var bytesStream = new MemoryStream(this._bytes);
4961

5062
var gifDecoder = new GifDecoder();
5163
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) {
@@ -57,8 +69,6 @@ IEnumerator _startDecoding(byte[] bytes, Window window) {
5769

5870
int i = 0;
5971
while (true) {
60-
yield return null;
61-
6272
if (gifDecoder.nextFrame() != GifDecoder.STATUS_OK) {
6373
throw new Exception("Failed to decode gif.");
6474
}
@@ -68,25 +78,14 @@ IEnumerator _startDecoding(byte[] bytes, Window window) {
6878
}
6979

7080
var frameData = new FrameData {
71-
gifFrame = gifDecoder.currentFrame,
81+
gifFrame = gifDecoder.currentFrame
7282
};
7383

74-
Promise<FrameData> frame;
75-
76-
lock (this._frames) {
77-
if (i < this._frames.Count) {
78-
}
79-
else {
80-
D.assert(this._frames.Count == i);
81-
this._frames.Add(new Promise<FrameData>());
82-
}
83-
84-
frame = this._frames[i];
85-
}
86-
87-
window.runInMain(() => { frame.Resolve(frameData); });
84+
this._frameData = frameData;
8885

8986
i++;
87+
88+
yield return null;
9089
}
9190

9291
D.assert(gifDecoder.frameCount == i);
@@ -107,54 +106,28 @@ public int repetitionCount {
107106
void _nextFrame() {
108107
this._frameIndex++;
109108

109+
this._coroutine.MoveNext();
110+
110111
if (this._isDone && this._frameIndex >= this._frameCount) {
111112
this._frameIndex = 0;
113+
this._isDone = false;
114+
this._coroutine = this._startDecoding();
115+
this._coroutine.MoveNext();
112116
}
113117
}
114118

115119
public IPromise<FrameInfo> getNextFrame() {
116-
Promise<FrameData> frame;
117-
118-
lock (this._frames) {
119-
if (this._frameIndex == this._frames.Count) {
120-
this._frames.Add(new Promise<FrameData>());
121-
}
122-
else {
123-
D.assert(this._frameIndex < this._frames.Count);
124-
}
125-
126-
frame = this._frames[this._frameIndex];
127-
}
128-
129-
130-
return frame.Then(frameData => {
131-
this._nextFrame();
132-
133-
if (this._texture == null) {
134-
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false);
135-
this._texture.hideFlags = HideFlags.HideAndDontSave;
136-
}
137-
138-
var tex = this._texture;
139-
tex.LoadRawTextureData(frameData.gifFrame.bytes);
140-
tex.Apply();
141-
142-
if (frameData.frameInfo != null) {
143-
return frameData.frameInfo;
144-
}
145-
146-
frameData.frameInfo = new FrameInfo {
147-
image = new Image(tex),
148-
duration = TimeSpan.FromMilliseconds(frameData.gifFrame.delay)
149-
};
150-
// frameData.gifFrame = null; // dispose gifFrame
151-
152-
return frameData.frameInfo;
153-
});
120+
this._nextFrame();
121+
this._texture.LoadRawTextureData(this._frameData.gifFrame.bytes);
122+
this._texture.Apply();
123+
this._frameData.frameInfo = new FrameInfo() {
124+
image = this._image,
125+
duration = TimeSpan.FromMilliseconds(this._frameData.gifFrame.delay)
126+
};
127+
return Promise<FrameInfo>.Resolved(this._frameData.frameInfo);
154128
}
155129

156130
public void Dispose() {
157-
this._coroutine.stop();
158131
}
159132
}
160133
}

0 commit comments

Comments
 (0)