-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathindex.js
265 lines (231 loc) · 9.27 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
import view from './view';
import { errMsgGlobal } from '../../../errMsg/index';
import show from '../../../libs/show';
import createRenderer from './render';
module.exports = function (PIXI, app, obj) {
let videoDecoder, frameData, currentTime, isPaused;
let videoSprite;
let baseTexture;
let texture;
let renderer;
let canvas;
// 初始化视频解码器
const initVideoDecoder = (data = {}) => {
if (wx.getSystemInfoSync().platform === 'devtools') {
show.Modal('开发者工具不支持,需要使用预览在真机进行调试', '提示');
return;
}
try {
const defaultConfig = {
source: 'https://baikebcs.bdimg.com/baike-other/big-buck-bunny.mp4',
width: 1280,
height: 720
};
const finalConfig = { ...defaultConfig, ...data };
console.log('开始初始化视频解码器', finalConfig);
// 创建视频解码器
try {
videoDecoder = wx.createVideoDecoder({
type: "wemedia"
});
console.log('视频解码器创建成功');
} catch (e) {
console.error('视频解码器创建失败:', e);
throw e;
}
// 创建渲染相关对象
try {
canvas = wx.createCanvas();
canvas.width = 1280; // 设置一个合适的初始宽度
canvas.height = 720; // 16:9 比例
if (!!GameGlobal.isIOSHighPerformanceModePlus) {
// 高性能+模式使用WebGL渲染器
renderer = createRenderer(canvas);
// 创建PIXI纹理,但使用WebGL渲染
baseTexture = new PIXI.BaseTexture(canvas);
texture = new PIXI.Texture(baseTexture);
} else {
// 普通模式使用PIXI
baseTexture = new PIXI.BaseTexture(canvas);
texture = new PIXI.Texture(baseTexture);
}
videoSprite = new PIXI.Sprite(texture);
console.log('渲染对象创建成功');
} catch (e) {
console.error('渲染对象创建失败:', e);
throw e;
}
// 设置精灵位置和大小
try {
const headerHeight = 150;
const availableHeight = obj.height - headerHeight;
const targetRatio = 16 / 9;
let displayWidth, displayHeight;
displayWidth = obj.width * 0.9;
displayHeight = displayWidth / targetRatio;
if (displayHeight > availableHeight * 0.8) {
displayHeight = availableHeight * 0.8;
displayWidth = displayHeight * targetRatio;
}
const xPos = (obj.width - displayWidth) / 2;
const yPos = headerHeight + (availableHeight - displayHeight) / 2;
videoSprite.width = displayWidth;
videoSprite.height = displayHeight;
videoSprite.x = xPos;
videoSprite.y = yPos;
console.log('Sprite位置和大小设置成功:', {
width: displayWidth,
height: displayHeight,
x: xPos,
y: yPos
});
} catch (e) {
console.error('精灵属性设置失败:', e);
throw e;
}
// 添加到舞台
try {
app.stage.addChild(videoSprite);
console.log('Sprite添加到舞台成功');
} catch (e) {
console.error('添加到舞台失败:', e);
throw e;
}
// 设置错误处理
videoDecoder.onError && videoDecoder.onError(res => {
console.error('视频解码器错误:', res);
for (let i = 0, errMsglist = Object.keys(errMsgGlobal); i < errMsglist.length; i++) {
if (res.errMsg.includes(errMsglist[i])) {
errMsgGlobal[errMsglist[i]]({
callback(res) {
show.Modal(res, '发生错误');
}
});
break;
}
}
});
// 监听解码器事件
videoDecoder.on("start", () => {
console.log('解码开始');
show.Toast('开始解码', 'success', 1000);
});
videoDecoder.on("stop", () => {
console.log('解码停止');
show.Toast('停止解码', 'success', 1000);
});
videoDecoder.on("ended", () => {
console.log('播放完成');
show.Toast('播放完成', 'success', 1000);
});
videoDecoder.on('frame', (res) => {
try {
closeFrame();
frameData = res;
currentTime = res.pts / 1000;
if (frameData) {
const { width, height, data } = frameData;
if (!!GameGlobal.isIOSHighPerformanceModePlus && renderer) {
// 高性能+模式:使用WebGL渲染器
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
}
renderer(data, width, height);
// 通知PIXI纹理更新
baseTexture.update();
} else {
// 普通模式:使用2D Canvas
const ctx = canvas.getContext('2d');
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
}
const imageData = ctx.createImageData(width, height);
imageData.data.set(new Uint8ClampedArray(data));
ctx.putImageData(imageData, 0, 0);
baseTexture.update();
}
}
} catch (e) {
console.error('帧处理失败:', e);
}
});
// 配置播放选项
const startOption = {
source: finalConfig.source,
mode: 1,
}
if (!!GameGlobal.isIOSHighPerformanceModePlus) {
startOption.videoDataType = 2;
}
console.log('开始播放视频,配置:', startOption);
// 开始播放
videoDecoder.start(startOption).catch(error => {
console.error('视频解码器启动失败:', error);
show.Modal('视频解码器启动失败', '错误');
});
// 监听小游戏前后台切换
wx.onHide(() => {
if (videoDecoder) {
videoDecoder.wait(true);
isPaused = true;
}
});
wx.onShow(() => {
if (videoDecoder && isPaused) {
videoDecoder.wait(false);
isPaused = false;
}
});
} catch (e) {
console.error('初始化失败,详细错误:', e);
console.error('错误堆栈:', e.stack);
show.Modal(`初始化失败: ${e.message}`, '错误');
throw e;
}
};
// 销毁渲染过的数据
const closeFrame = () => {
if (frameData) {
frameData.close?.();
}
frameData = null;
};
return view(PIXI, app, obj, res => {
const { status, data = {} } = res;
switch (status) {
case 'createVideoDecoder':
try {
console.log('收到创建视频解码器请求:', data);
initVideoDecoder(data);
} catch (e) {
console.error('视频解码器创建失败:', e);
}
break;
case 'destroy':
console.log('开始清理资源');
if (videoDecoder) {
videoDecoder.stop();
videoDecoder = null;
}
closeFrame();
if (videoSprite) {
app.stage.removeChild(videoSprite);
if (texture) {
texture.destroy(true);
}
if (baseTexture) {
baseTexture.destroy();
}
videoSprite.destroy();
videoSprite = null;
texture = null;
baseTexture = null;
renderer = null;
}
console.log('资源清理完成');
break;
}
});
};