[*] 日常优化
This commit is contained in:
@@ -620,7 +620,9 @@ public final class Taoyao implements ITaoyao {
|
|||||||
* @param message 信令消息
|
* @param message 信令消息
|
||||||
*/
|
*/
|
||||||
private void dispatch(final String content, final Header header, final Message message) {
|
private void dispatch(final String content, final Header header, final Message message) {
|
||||||
if(this.taoyaoListener.preOnMessage(message)) {
|
final boolean done = this.taoyaoListener.preOnMessage(message);
|
||||||
|
if(done) {
|
||||||
|
Log.d(Taoyao.class.getSimpleName(), "信令前置处理完成:" + message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (header.getSignal()) {
|
switch (header.getSignal()) {
|
||||||
|
|||||||
@@ -15,52 +15,59 @@ import java.util.function.Function;
|
|||||||
public interface ITaoyao {
|
public interface ITaoyao {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param signal 信令
|
* @param signal 信令标识
|
||||||
* @param args 消息主体内容
|
* @param args 消息主体
|
||||||
*
|
*
|
||||||
* @return 消息
|
* @return 信令消息
|
||||||
*/
|
*/
|
||||||
Message buildMessage(String signal, Object ... args);
|
Message buildMessage(String signal, Object ... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param signal 信令
|
* @param signal 信令标识
|
||||||
* @param body 消息主体
|
* @param body 消息主体
|
||||||
*
|
*
|
||||||
* @return 消息
|
* @return 信令消息
|
||||||
*/
|
*/
|
||||||
Message buildMessage(String signal, Object body);
|
Message buildMessage(String signal, Object body);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 推送信令消息
|
||||||
|
*
|
||||||
* @param message 信令消息
|
* @param message 信令消息
|
||||||
*/
|
*/
|
||||||
void push(Message message);
|
void push(Message message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param request 信令请求消息
|
* 请求信令消息
|
||||||
*
|
*
|
||||||
* @return 信令响应消息
|
* @param request 请求信令消息
|
||||||
|
*
|
||||||
|
* @return 响应信令消息
|
||||||
*/
|
*/
|
||||||
Message request(Message request);
|
Message request(Message request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param request 信令请求消息
|
* 请求信令消息
|
||||||
* @param success 成功
|
|
||||||
*
|
*
|
||||||
* @return 结果
|
* @param request 请求信令消息
|
||||||
|
* @param success 成功请求执行
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
default <T> T requestFuture(Message request, Function<Message, T> success) {
|
default <T> T requestFuture(Message request, Function<Message, T> success) {
|
||||||
return this.requestFuture(request, success, null);
|
return this.requestFuture(request, success, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param request 信令请求消息
|
* 请求信令消息
|
||||||
* @param success 成功
|
|
||||||
* @param failure 失败
|
|
||||||
*
|
*
|
||||||
* @return 结果
|
* @param request 请求信令消息
|
||||||
|
* @param success 成功请求执行
|
||||||
|
* @param failure 失败请求执行
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
*/
|
*/
|
||||||
default <T> T requestFuture(Message request, Function<Message, T> success, Function<Message, T> failure) {
|
default <T> T requestFuture(Message request, Function<Message, T> success, Function<Message, T> failure) {
|
||||||
// final CompletableFuture<Message> completableFuture = new CompletableFuture<>();
|
|
||||||
final Message response = this.request(request);
|
final Message response = this.request(request);
|
||||||
if(response != null && response.isSuccess()) {
|
if(response != null && response.isSuccess()) {
|
||||||
return success.apply(response);
|
return success.apply(response);
|
||||||
@@ -74,20 +81,23 @@ public interface ITaoyao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param request 信令请求消息
|
* 请求信令消息
|
||||||
* @param success 成功
|
*
|
||||||
|
* @param request 请求信令消息
|
||||||
|
* @param success 成功请求执行
|
||||||
*/
|
*/
|
||||||
default void requestFuture(Message request, Consumer<Message> success) {
|
default void requestFuture(Message request, Consumer<Message> success) {
|
||||||
this.requestFuture(request, success, null);
|
this.requestFuture(request, success, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 请求信令消息
|
||||||
|
*
|
||||||
* @param request 信令请求消息
|
* @param request 信令请求消息
|
||||||
* @param success 成功
|
* @param success 成功请求执行
|
||||||
* @param failure 失败
|
* @param failure 失败请求执行
|
||||||
*/
|
*/
|
||||||
default void requestFuture(Message request, Consumer<Message> success, Consumer<Message> failure) {
|
default void requestFuture(Message request, Consumer<Message> success, Consumer<Message> failure) {
|
||||||
// final CompletableFuture<Message> completableFuture = new CompletableFuture<>();
|
|
||||||
final Message response = this.request(request);
|
final Message response = this.request(request);
|
||||||
if(response != null && response.isSuccess()) {
|
if(response != null && response.isSuccess()) {
|
||||||
success.accept(response);
|
success.accept(response);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public interface ITaoyaoListener {
|
|||||||
*
|
*
|
||||||
* @param message 信令消息
|
* @param message 信令消息
|
||||||
*
|
*
|
||||||
* @return 是否继续处理信令
|
* @return 是否完成
|
||||||
*/
|
*/
|
||||||
default boolean preOnMessage(Message message) {
|
default boolean preOnMessage(Message message) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import org.webrtc.VideoFrame;
|
|||||||
*/
|
*/
|
||||||
public class AiProcesser extends VideoProcesser {
|
public class AiProcesser extends VideoProcesser {
|
||||||
|
|
||||||
|
public AiProcesser() {
|
||||||
|
super("AI识别处理器");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doProcess(VideoFrame.I420Buffer i420Buffer) {
|
protected void doProcess(VideoFrame.I420Buffer i420Buffer) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,36 @@
|
|||||||
package com.acgist.taoyao.media.video;
|
package com.acgist.taoyao.media.video;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.webrtc.VideoFrame;
|
import org.webrtc.VideoFrame;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频处理器
|
* 视频处理器
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
public abstract class VideoProcesser implements Closeable {
|
public abstract class VideoProcesser implements Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理器名称
|
||||||
|
*/
|
||||||
|
protected final String name;
|
||||||
|
/**
|
||||||
|
* 下一个视频处理器
|
||||||
|
*/
|
||||||
protected VideoProcesser next;
|
protected VideoProcesser next;
|
||||||
|
|
||||||
|
public VideoProcesser(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频帧
|
||||||
|
*
|
||||||
|
* @param i420Buffer 视频帧
|
||||||
|
*/
|
||||||
public void process(VideoFrame.I420Buffer i420Buffer) {
|
public void process(VideoFrame.I420Buffer i420Buffer) {
|
||||||
this.doProcess(i420Buffer);
|
this.doProcess(i420Buffer);
|
||||||
if(this.next == null) {
|
if(this.next == null) {
|
||||||
@@ -20,9 +40,18 @@ public abstract class VideoProcesser implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频帧
|
||||||
|
*
|
||||||
|
* @param i420Buffer 视频帧
|
||||||
|
*/
|
||||||
protected abstract void doProcess(VideoFrame.I420Buffer i420Buffer);
|
protected abstract void doProcess(VideoFrame.I420Buffer i420Buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭处理器
|
||||||
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
|
Log.i(VideoProcesser.class.getSimpleName(), "关闭视频处理器:" + this.name);
|
||||||
if(this.next == null) {
|
if(this.next == null) {
|
||||||
// 忽略
|
// 忽略
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -29,40 +29,84 @@ import java.util.TimerTask;
|
|||||||
*/
|
*/
|
||||||
public class WatermarkProcesser extends VideoProcesser {
|
public class WatermarkProcesser extends VideoProcesser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符矩阵
|
||||||
|
*/
|
||||||
private static final WatermarkMatrix[] MATRICES = new WatermarkMatrix[256];
|
private static final WatermarkMatrix[] MATRICES = new WatermarkMatrix[256];
|
||||||
|
/**
|
||||||
|
* 水印字符
|
||||||
|
*/
|
||||||
|
private static final String WATERMARK = "-: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间格式
|
||||||
|
*/
|
||||||
private final String format;
|
private final String format;
|
||||||
|
/**
|
||||||
|
* 格式
|
||||||
|
*/
|
||||||
|
private final DateTimeFormatter formatter;
|
||||||
|
/**
|
||||||
|
* 视频宽度
|
||||||
|
*/
|
||||||
private final int width;
|
private final int width;
|
||||||
|
/**
|
||||||
|
* 视频高度
|
||||||
|
*/
|
||||||
private final int height;
|
private final int height;
|
||||||
|
/**
|
||||||
|
* 定时器
|
||||||
|
*/
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
|
/**
|
||||||
|
* 字符矩阵
|
||||||
|
*/
|
||||||
private final WatermarkMatrix[] watermark;
|
private final WatermarkMatrix[] watermark;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final char[] chars = WATERMARK.toCharArray();
|
||||||
|
for (char value : chars) {
|
||||||
|
WatermarkProcesser.build(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param format 时间格式
|
||||||
|
* @param width 视频宽度
|
||||||
|
* @param height 视频高度
|
||||||
|
*/
|
||||||
public WatermarkProcesser(String format, int width, int height) {
|
public WatermarkProcesser(String format, int width, int height) {
|
||||||
|
super("水印处理器");
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
final String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern(format));
|
this.formatter = DateTimeFormatter.ofPattern(format);
|
||||||
this.watermark = new WatermarkMatrix[date.length()];
|
final String date = LocalDateTime.now().format(this.formatter);
|
||||||
this.timer = new Timer("Watermark-Timer", true);
|
this.watermark = new WatermarkMatrix[date.length()];
|
||||||
|
this.timer = new Timer("Watermark-Timer", true);
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param format 时间格式
|
||||||
|
* @param width 视频宽度
|
||||||
|
* @param height 视频高度
|
||||||
|
* @param videoProcesser 下个视频处理器
|
||||||
|
*/
|
||||||
public WatermarkProcesser(String format, int width, int height, VideoProcesser videoProcesser) {
|
public WatermarkProcesser(String format, int width, int height, VideoProcesser videoProcesser) {
|
||||||
this(format, width, height);
|
this(format, width, height);
|
||||||
this.next = videoProcesser;
|
this.next = videoProcesser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载水印
|
||||||
|
*/
|
||||||
private void init() {
|
private void init() {
|
||||||
final String source = "-: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
||||||
final char[] chars = source.toCharArray();
|
|
||||||
for (char value : chars) {
|
|
||||||
this.build(value);
|
|
||||||
}
|
|
||||||
this.timer.schedule(new TimerTask() {
|
this.timer.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
final char[] chars = LocalDateTime.now().format(DateTimeFormatter.ofPattern(WatermarkProcesser.this.format)).toCharArray();
|
final char[] chars = LocalDateTime.now().format(WatermarkProcesser.this.formatter).toCharArray();
|
||||||
for (char value : chars) {
|
for (char value : chars) {
|
||||||
WatermarkProcesser.this.watermark[index] = MATRICES[value];
|
WatermarkProcesser.this.watermark[index] = MATRICES[value];
|
||||||
index++;
|
index++;
|
||||||
@@ -71,21 +115,25 @@ public class WatermarkProcesser extends VideoProcesser {
|
|||||||
}, 1000, 1000);
|
}, 1000, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void build(char source) {
|
/**
|
||||||
// TODO:优化复用bitmap
|
* 创建字符矩阵
|
||||||
final String target = Character.toString(source);
|
*
|
||||||
|
* @param source 字符
|
||||||
|
*/
|
||||||
|
private static void build(char source) {
|
||||||
final Paint paint = new Paint();
|
final Paint paint = new Paint();
|
||||||
paint.setColor(Color.WHITE);
|
paint.setColor(Color.WHITE);
|
||||||
paint.setDither(true);
|
paint.setDither(true);
|
||||||
paint.setTextSize(40.0F);
|
paint.setTextSize(40.0F);
|
||||||
paint.setTextAlign(Paint.Align.LEFT);
|
paint.setTextAlign(Paint.Align.LEFT);
|
||||||
paint.setFilterBitmap(true);
|
paint.setFilterBitmap(true);
|
||||||
final Paint.FontMetricsInt box = paint.getFontMetricsInt();
|
final Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
|
||||||
final int width = (int) paint.measureText(target);
|
final String target = Character.toString(source);
|
||||||
final int height = box.descent - box.ascent;
|
final int width = (int) paint.measureText(target);
|
||||||
|
final int height = fontMetricsInt.descent - fontMetricsInt.ascent;
|
||||||
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
final Canvas canvas = new Canvas(bitmap);
|
final Canvas canvas = new Canvas(bitmap);
|
||||||
canvas.drawText(target, 0, box.leading - box.ascent, paint);
|
canvas.drawText(target, 0, fontMetricsInt.leading - fontMetricsInt.ascent, paint);
|
||||||
canvas.save();
|
canvas.save();
|
||||||
final boolean[][] matrix = new boolean[width][height];
|
final boolean[][] matrix = new boolean[width][height];
|
||||||
for (int j = 0; j < height; j++) {
|
for (int j = 0; j < height; j++) {
|
||||||
@@ -97,16 +145,16 @@ public class WatermarkProcesser extends VideoProcesser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MATRICES[source] = new WatermarkMatrix(width, height, matrix);
|
|
||||||
bitmap.recycle();
|
bitmap.recycle();
|
||||||
|
WatermarkProcesser.MATRICES[source] = new WatermarkMatrix(width, height, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doProcess(VideoFrame.I420Buffer i420Buffer) {
|
protected void doProcess(VideoFrame.I420Buffer i420Buffer) {
|
||||||
int widthPos = 0;
|
int widthPos = 0;
|
||||||
int heightPos = 0;
|
int heightPos = 0;
|
||||||
final ByteBuffer buffer = i420Buffer.getDataY();
|
final ByteBuffer buffer = i420Buffer.getDataY();
|
||||||
for (WatermarkMatrix matrix : watermark) {
|
for (WatermarkMatrix matrix : this.watermark) {
|
||||||
if(matrix == null) {
|
if(matrix == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -117,7 +165,7 @@ public class WatermarkProcesser extends VideoProcesser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widthPos += matrix.width;
|
widthPos += matrix.width;
|
||||||
heightPos += matrix.height;
|
heightPos += matrix.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,12 +176,31 @@ public class WatermarkProcesser extends VideoProcesser {
|
|||||||
this.timer.cancel();
|
this.timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水印矩阵
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
static class WatermarkMatrix {
|
static class WatermarkMatrix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符宽度
|
||||||
|
*/
|
||||||
int width;
|
int width;
|
||||||
|
/**
|
||||||
|
* 字符高度
|
||||||
|
*/
|
||||||
int height;
|
int height;
|
||||||
|
/**
|
||||||
|
* 字符矩阵
|
||||||
|
*/
|
||||||
boolean[][] matrix;
|
boolean[][] matrix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param width 字符宽度
|
||||||
|
* @param height 字符高度
|
||||||
|
* @param matrix 字符矩阵
|
||||||
|
*/
|
||||||
public WatermarkMatrix(int width, int height, boolean[][] matrix) {
|
public WatermarkMatrix(int width, int height, boolean[][] matrix) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|||||||
Reference in New Issue
Block a user