1515 */
1616package com .tencent .qgame .playerproj .animtool ;
1717
18+ import com .tencent .qgame .playerproj .animtool .vapx .FrameSet ;
19+ import com .tencent .qgame .playerproj .animtool .vapx .GetMaskFrame ;
20+ import com .tencent .qgame .playerproj .animtool .vapx .SrcSet ;
21+
1822import javax .imageio .ImageIO ;
1923import java .awt .image .BufferedImage ;
20- import java .io .BufferedReader ;
2124import java .io .BufferedWriter ;
2225import java .io .File ;
2326import java .io .FileWriter ;
2427import java .io .IOException ;
25- import java .io .InputStreamReader ;
26- import java .util .concurrent .TimeUnit ;
2728
2829public class AnimTool {
2930
@@ -32,7 +33,8 @@ public class AnimTool {
3233 public static final String OUTPUT_DIR = "output" + File .separator ;
3334 public static final String FRAME_IMAGE_DIR = "frames" + File .separator ;
3435 public static final String VIDEO_FILE = "video.mp4" ;
35- public static final String TEM_VIDEO_FILE = "tmp_video.mp4" ;
36+ public static final String TEMP_VIDEO_FILE = "tmp_video.mp4" ;
37+ public static final String TEMP_VIDEO_AUDIO_FILE = "tmp_video_audio.mp4" ;
3638 public static final String VAPC_BIN_FILE = "vapc.bin" ;
3739 public static final String VAPC_JSON_FILE = "vapc.json" ;
3840
@@ -42,6 +44,7 @@ public class AnimTool {
4244 private volatile int finishThreadCount = 0 ;
4345 private long time ;
4446 private GetAlphaFrame getAlphaFrame = new GetAlphaFrame ();
47+ private GetMaskFrame getMaskFrame = new GetMaskFrame ();
4548 private IToolListener toolListener ;
4649
4750 public void setToolListener (IToolListener toolListener ) {
@@ -57,7 +60,7 @@ public void create(final CommonArg commonArg, final boolean needVideo) throws Ex
5760 createAllFrameImage (commonArg , new Runnable () {
5861 @ Override
5962 public void run () {
60- if (needVideo ) {
63+ if (finalCheck ( commonArg ) && needVideo ) {
6164 // 最终生成视频文件
6265 createVideo (commonArg );
6366 }
@@ -71,7 +74,23 @@ public void run() {
7174 * @return
7275 */
7376 private boolean checkCommonArg (CommonArg commonArg ) throws Exception {
74- return CommonArgTool .autoFillAndCheck (commonArg );
77+ return CommonArgTool .autoFillAndCheck (commonArg , toolListener );
78+ }
79+
80+ private boolean finalCheck (CommonArg commonArg ) {
81+ if (commonArg .isVapx ) {
82+ if (commonArg .srcSet .srcs .isEmpty ()) {
83+ TLog .i (TAG , "vapx error: src is empty" );
84+ return false ;
85+ }
86+ for (SrcSet .Src src : commonArg .srcSet .srcs ) {
87+ if (src .w <=0 || src .h <= 0 ) {
88+ TLog .i (TAG , "vapx error: src.id=" + src .srcId + ",src.w=" + src .w + ",src.h=" + src .h );
89+ return false ;
90+ }
91+ }
92+ }
93+ return true ;
7594 }
7695
7796 private void createAllFrameImage (final CommonArg commonArg , final Runnable finishRunnable ) throws Exception {
@@ -107,6 +126,11 @@ private void createAllFrameImage(final CommonArg commonArg, final Runnable finis
107126 @ Override
108127 public void run () {
109128 for (int i = threadIndexSet [k ][0 ]; i <threadIndexSet [k ][1 ]; i ++) {
129+ try {
130+ createFrame (commonArg , i );
131+ } catch (Exception e ) {
132+ e .printStackTrace ();
133+ }
110134 synchronized (AnimTool .class ) {
111135 totalP ++;
112136 float progress = totalP * 1.0f / commonArg .totalFrame ;
@@ -116,11 +140,6 @@ public void run() {
116140 TLog .i (TAG , "progress " + progress );
117141 }
118142 }
119- try {
120- createFrame (commonArg , i );
121- } catch (Exception e ) {
122- e .printStackTrace ();
123- }
124143 }
125144 synchronized (AnimTool .class ) {
126145 finishThreadCount ++;
@@ -141,18 +160,21 @@ public void run() {
141160 }
142161
143162 private void createFrame (CommonArg commonArg , int frameIndex ) throws Exception {
144- int w = commonArg .videoW ;
145- int h = commonArg .videoH ;
146163 File inputFile = new File (commonArg .inputPath + String .format ("%03d" , frameIndex )+".png" );
147- GetAlphaFrame .AlphaFrameOut videoFrame = getAlphaFrame .createFrame (commonArg .orin , w , h ,
148- commonArg .gap , commonArg .wFill , commonArg .hFill , inputFile );
164+ GetAlphaFrame .AlphaFrameOut videoFrame = getAlphaFrame .createFrame (commonArg , inputFile );
165+ if (commonArg .isVapx ) {
166+ FrameSet .FrameObj frameObj = getMaskFrame .getFrameObj (frameIndex , commonArg , videoFrame .argb );
167+ if (frameObj != null ) {
168+ commonArg .frameSet .frameObjs .add (frameObj );
169+ }
170+ }
149171 if (videoFrame == null ) {
150172 TLog .i (TAG , "frameIndex=" +frameIndex +" is empty" );
151173 return ;
152174 }
153175 // 最后保存图片
154- BufferedImage outBuf = new BufferedImage (videoFrame . outW , videoFrame . outH , BufferedImage .TYPE_INT_ARGB );
155- outBuf .setRGB (0 ,0 , videoFrame . outW , videoFrame . outH , videoFrame .argb , 0 , videoFrame . outW );
176+ BufferedImage outBuf = new BufferedImage (commonArg . outputW , commonArg . outputH , BufferedImage .TYPE_INT_ARGB );
177+ outBuf .setRGB (0 ,0 , commonArg . outputW , commonArg . outputH , videoFrame .argb , 0 , commonArg . outputW );
156178
157179 File outputFile = new File (commonArg .frameOutputPath + String .format ("%03d" , frameIndex ) +".png" );
158180 ImageIO .write (outBuf , "PNG" , outputFile );
@@ -180,17 +202,30 @@ private void createVideo(CommonArg commonArg){
180202 TLog .i (TAG , "createMp4 fail" );
181203 return ;
182204 }
205+ String tempVideoName = TEMP_VIDEO_FILE ;
206+ if (commonArg .needAudio ) {
207+ result = mergeAudio2Mp4 (commonArg , tempVideoName );
208+ if (!result ) {
209+ TLog .i (TAG , "mergeAudio2Mp4 fail" );
210+ return ;
211+ }
212+ tempVideoName = TEMP_VIDEO_AUDIO_FILE ;
213+ }
214+
183215 String input = commonArg .outputPath + VAPC_JSON_FILE ;
184216 // 由json变为bin文件
185217 String vapcBinPath = mp4BoxTool (input , commonArg .outputPath );
186218 // 将bin文件合并到mp4里
187- result = mergeBin2Mp4 (commonArg , vapcBinPath , commonArg .outputPath );
219+ result = mergeBin2Mp4 (commonArg , vapcBinPath , tempVideoName , commonArg .outputPath );
188220 if (!result ) {
189221 TLog .i (TAG , "mergeBin2Mp4 fail" );
190222 return ;
191223 }
192224 // 删除临时视频文件
193- new File (commonArg .outputPath + TEM_VIDEO_FILE ).delete ();
225+ new File (commonArg .outputPath + TEMP_VIDEO_FILE ).delete ();
226+ if (commonArg .needAudio ) {
227+ new File (commonArg .outputPath + TEMP_VIDEO_AUDIO_FILE ).delete ();
228+ }
194229 new File (commonArg .outputPath + VAPC_BIN_FILE ).delete ();
195230 // 计算文件md5
196231 String md5 = new Md5Util ().getFileMD5 (new File (commonArg .outputPath + VIDEO_FILE ), commonArg .outputPath );
@@ -205,36 +240,34 @@ private void createVideo(CommonArg commonArg){
205240 * @param commonArg
206241 */
207242 private void createVapcJson (CommonArg commonArg ) {
208- String json = "{\" info\" :{\" v\" :$(v),\" f\" :$(f),\" w\" :$(w),\" h\" :$(h),\" videoW\" :$(videoW),\" videoH\" :$(videoH),\" orien\" :0,\" fps\" :$(fps),\" isVapx\" :0,\" aFrame\" :$(aFrame),\" rgbFrame\" :$(rgbFrame)}}" ;
209- json = json .replace ("$(v)" , String .valueOf (commonArg .version ));
210- json = json .replace ("$(f)" , String .valueOf (commonArg .totalFrame ));
211- json = json .replace ("$(w)" , String .valueOf (commonArg .videoW ));
212- json = json .replace ("$(h)" , String .valueOf (commonArg .videoH ));
213- json = json .replace ("$(fps)" , String .valueOf (commonArg .fps ));
214- int realW = 0 ;
215- int realH = 0 ;
216- int cx , cy ;
217- String aFrame = "[0,0," +commonArg .videoW +"," +commonArg .videoH +"]" ;
218- String rgbFrame = "[0,0,0,0]" ;
219- if (commonArg .orin == CommonArg .ORIN_H ) { // 水平对齐
220- realW = 2 * commonArg .videoW + commonArg .gap ;
221- realH = commonArg .videoH ;
222- cx = commonArg .videoW + commonArg .gap ;
223- cy = 0 ;
224- } else { // 上下对齐
225- realW = commonArg .videoW ;
226- realH = 2 * commonArg .videoH + commonArg .gap ;
227- cx = 0 ;
228- cy = commonArg .videoH + commonArg .gap ;
243+
244+ String json = "\" info\" :{" +
245+ "\" v\" :" + commonArg .version + "," +
246+ "\" f\" :" + commonArg .totalFrame + "," +
247+ "\" w\" :" + commonArg .rgbPoint .w + "," +
248+ "\" h\" :" + commonArg .rgbPoint .h + "," +
249+ "\" fps\" :" + commonArg .fps + "," +
250+ "\" videoW\" :" + commonArg .outputW + "," +
251+ "\" videoH\" :" + commonArg .outputH + "," +
252+ "\" aFrame\" :" + commonArg .alphaPoint .toString () + "," +
253+ "\" rgbFrame\" :" + commonArg .rgbPoint .toString () + "," +
254+ "\" isVapx\" :" + (commonArg .isVapx ? 1 : 0 ) + "," +
255+ "\" orien\" :" + 0 +
256+ "}" ;
257+ TLog .i (TAG , "{" + json + "}" );
258+
259+ StringBuilder sb = new StringBuilder ();
260+ sb .append ("{" );
261+ sb .append (json );
262+ if (commonArg .isVapx ) {
263+ sb .append ("," );
264+ sb .append (commonArg .srcSet .toString ());
265+ sb .append ("," );
266+ sb .append (commonArg .frameSet .toString ());
229267 }
230- rgbFrame = "[" +cx +"," +cy +"," +commonArg .videoW +"," +commonArg .videoH +"]" ;
231-
232- realW += commonArg .wFill ;
233- realH += commonArg .hFill ;
234- json = json .replace ("$(videoW)" , String .valueOf (realW ));
235- json = json .replace ("$(videoH)" , String .valueOf (realH ));
236- json = json .replace ("$(aFrame)" , aFrame );
237- json = json .replace ("$(rgbFrame)" , rgbFrame );
268+ sb .append ("}" );
269+ json = sb .toString ();
270+
238271 try {
239272 BufferedWriter writer = new BufferedWriter (new FileWriter (commonArg .outputPath + VAPC_JSON_FILE ));
240273 writer .write (json );
@@ -244,8 +277,6 @@ private void createVapcJson(CommonArg commonArg) {
244277 e .printStackTrace ();
245278 throw new RuntimeException ();
246279 }
247- TLog .i (TAG ,json );
248-
249280 }
250281
251282
@@ -254,8 +285,6 @@ private void createVapcJson(CommonArg commonArg) {
254285
255286 /**
256287 * 创建mp4
257- * @param commonArg
258- * @throws Exception
259288 */
260289 private boolean createMp4 (CommonArg commonArg , String videoPath , String frameImagePath ) throws Exception {
261290 String [] cmd = null ;
@@ -269,17 +298,18 @@ private boolean createMp4(CommonArg commonArg, String videoPath, String frameIma
269298 "-level" , "4.0" ,
270299 "-tag:v" , "hvc1" ,
271300 "-bufsize" , "2000k" ,
272- "-y" , videoPath + TEM_VIDEO_FILE };
301+ "-y" , videoPath + TEMP_VIDEO_FILE };
273302 } else {
274303 cmd = new String []{commonArg .ffmpegCmd , "-r" , String .valueOf (commonArg .fps ),
275304 "-i" , frameImagePath + "%03d.png" ,
276305 "-pix_fmt" , "yuv420p" ,
277306 "-vcodec" , "libx264" ,
278307 "-b:v" , "3000k" ,
279- "-profile:v" , "baseline " ,
280- "-level" , "3 .0" ,
308+ "-profile:v" , "main " ,
309+ "-level" , "4 .0" ,
281310 "-bf" , "0" ,
282- "-y" , videoPath + TEM_VIDEO_FILE };
311+ "-bufsize" , "3000k" ,
312+ "-y" , videoPath + TEMP_VIDEO_FILE };
283313 }
284314
285315 TLog .i (TAG , "run createMp4" );
@@ -288,13 +318,28 @@ private boolean createMp4(CommonArg commonArg, String videoPath, String frameIma
288318 return result == 0 ;
289319 }
290320
321+ /**
322+ * 合并音频文件
323+ */
324+ private boolean mergeAudio2Mp4 (CommonArg commonArg , String tempVideoFile ) throws Exception {
325+ String [] cmd = new String [] {commonArg .ffmpegCmd ,
326+ "-i" , commonArg .audioPath ,
327+ "-i" , commonArg .outputPath + tempVideoFile ,
328+ "-c:v" , "copy" ,
329+ "-c:a" , "aac" ,
330+ "-y" , commonArg .outputPath + TEMP_VIDEO_AUDIO_FILE };
331+ TLog .i (TAG , "run mergeAudio2Mp4" );
332+ int result = ProcessUtil .run (cmd );
333+ TLog .i (TAG , "mergeAudio2Mp4 result=" + (result == 0 ? "success" : "fail" ));
334+ return result == 0 ;
335+ }
336+
337+
291338 /**
292339 * 合并vapc.bin到mp4里
293- * @param inputFile
294- * @throws Exception
295340 */
296- private boolean mergeBin2Mp4 (CommonArg commonArg , String inputFile , String videoPath ) throws Exception {
297- String [] cmd = new String [] {commonArg .mp4editCmd , "--insert" , ":" +inputFile +":1" , videoPath + TEM_VIDEO_FILE , videoPath + VIDEO_FILE };
341+ private boolean mergeBin2Mp4 (CommonArg commonArg , String inputFile , String tempVideoFile , String videoPath ) throws Exception {
342+ String [] cmd = new String [] {commonArg .mp4editCmd , "--insert" , ":" +inputFile +":1" , videoPath + tempVideoFile , videoPath + VIDEO_FILE };
298343 TLog .i (TAG , "run mergeBin2Mp4" );
299344 int result = ProcessUtil .run (cmd );
300345 TLog .i (TAG , "mergeBin2Mp4 result=" + (result == 0 ? "success" : "fail" ));
@@ -313,6 +358,7 @@ private String mp4BoxTool(String inputFile, String outputPath) throws Exception
313358
314359 public interface IToolListener {
315360 void onProgress (float progress );
361+ void onWarning (String msg );
316362 void onError ();
317363 void onComplete ();
318364 }
0 commit comments