Clean up BitmapFactoryVideoRenderer

This commit is contained in:
Dustin 2022-01-29 11:00:23 -07:00
parent b520b26f0f
commit 9d88db7119

View File

@ -24,17 +24,22 @@ import java.nio.ByteBuffer;
public class BitmapFactoryVideoRenderer extends BaseRenderer { public class BitmapFactoryVideoRenderer extends BaseRenderer {
private static final String TAG = "BitmapFactoryRenderer"; private static final String TAG = "BitmapFactoryRenderer";
final VideoRendererEventListener.EventDispatcher eventDispatcher; private static int threadId;
@Nullable
volatile Surface surface;
private final Rect rect = new Rect(); private final Rect rect = new Rect();
private final Point lastSurface = new Point(); private final Point lastSurface = new Point();
private final RenderRunnable renderRunnable = new RenderRunnable(); private final RenderRunnable renderRunnable = new RenderRunnable();
private final Thread thread = new Thread(renderRunnable, "BitmapFactoryVideoRenderer");
final VideoRendererEventListener.EventDispatcher eventDispatcher;
final Thread thread = new Thread(renderRunnable, getClass().getSimpleName() + threadId++);
@Nullable
volatile Surface surface;
private VideoSize lastVideoSize = VideoSize.UNKNOWN; private VideoSize lastVideoSize = VideoSize.UNKNOWN;
private long currentTimeUs; private long currentTimeUs;
private long frameUs; private long frameUs;
boolean ended; private boolean firstFrameRendered;
@Nullable @Nullable
private DecoderCounters decoderCounters; private DecoderCounters decoderCounters;
@ -60,8 +65,7 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
@Override @Override
protected void onDisabled() { protected void onDisabled() {
renderRunnable.running = false; renderRunnable.stop();
thread.interrupt();
@Nullable @Nullable
final DecoderCounters decoderCounters = this.decoderCounters; final DecoderCounters decoderCounters = this.decoderCounters;
@ -111,7 +115,7 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
@Override @Override
public boolean isEnded() { public boolean isEnded() {
return renderRunnable.ended; return renderRunnable.isEnded();
} }
@Override @Override
@ -123,11 +127,67 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} }
void renderBitmap(final Bitmap bitmap) {
@Nullable
final Surface surface = this.surface;
if (surface == null) {
return;
}
//Log.d(TAG, "Drawing: " + bitmap.getWidth() + "x" + bitmap.getHeight());
final Canvas canvas = surface.lockCanvas(null);
final Rect clipBounds = canvas.getClipBounds();
final VideoSize videoSize = new VideoSize(bitmap.getWidth(), bitmap.getHeight());
final boolean videoSizeChanged;
if (videoSize.equals(lastVideoSize)) {
videoSizeChanged = false;
} else {
lastVideoSize = videoSize;
eventDispatcher.videoSizeChanged(videoSize);
videoSizeChanged = true;
}
if (lastSurface.x != clipBounds.width() || lastSurface.y != clipBounds.height() ||
videoSizeChanged) {
lastSurface.x = clipBounds.width();
lastSurface.y = clipBounds.height();
final float scaleX = lastSurface.x / (float)videoSize.width;
final float scaleY = lastSurface.y / (float)videoSize.height;
final float scale = Math.min(scaleX, scaleY);
final float width = videoSize.width * scale;
final float height = videoSize.height * scale;
final int x = (int)(lastSurface.x - width) / 2;
final int y = (int)(lastSurface.y - height) / 2;
rect.set(x, y, x + (int)width, y + (int) height);
}
canvas.drawBitmap(bitmap, null, rect, null);
surface.unlockCanvasAndPost(canvas);
@Nullable
final DecoderCounters decoderCounters = BitmapFactoryVideoRenderer.this.decoderCounters;
if (decoderCounters != null) {
decoderCounters.renderedOutputBufferCount++;
}
if (!firstFrameRendered) {
firstFrameRendered = true;
eventDispatcher.renderedFirstFrame(surface);
}
}
class RenderRunnable implements Runnable { class RenderRunnable implements Runnable {
private volatile boolean ended; final DecoderInputBuffer decoderInputBuffer =
private boolean firstFrameRendered; new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
private volatile boolean running = true; private volatile boolean running = true;
void stop() {
running = false;
thread.interrupt();
}
boolean isEnded() {
return !running || decoderInputBuffer.isEndOfStream();
}
@Nullable @Nullable
private Bitmap decodeInputBuffer(final DecoderInputBuffer decoderInputBuffer) { private Bitmap decodeInputBuffer(final DecoderInputBuffer decoderInputBuffer) {
@Nullable final ByteBuffer byteBuffer = decoderInputBuffer.data; @Nullable final ByteBuffer byteBuffer = decoderInputBuffer.data;
@ -148,50 +208,6 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
return null; return null;
} }
private void renderBitmap(final Bitmap bitmap, @Nullable final Surface surface) {
if (surface == null) {
return;
}
//Log.d(TAG, "Drawing: " + bitmap.getWidth() + "x" + bitmap.getHeight());
final Canvas canvas = surface.lockCanvas(null);
final Rect clipBounds = canvas.getClipBounds();
final VideoSize videoSize = new VideoSize(bitmap.getWidth(), bitmap.getHeight());
final boolean videoSizeChanged;
if (videoSize.equals(lastVideoSize)) {
videoSizeChanged = false;
} else {
lastVideoSize = videoSize;
eventDispatcher.videoSizeChanged(videoSize);
videoSizeChanged = true;
}
if (lastSurface.x != clipBounds.width() || lastSurface.y != clipBounds.height() ||
videoSizeChanged) {
lastSurface.x = clipBounds.width();
lastSurface.y = clipBounds.height();
final float scaleX = lastSurface.x / (float)videoSize.width;
final float scaleY = lastSurface.y / (float)videoSize.height;
final float scale = Math.min(scaleX, scaleY);
final float width = videoSize.width * scale;
final float height = videoSize.height * scale;
final int x = (int)(lastSurface.x - width) / 2;
final int y = (int)(lastSurface.y - height) / 2;
rect.set(x, y, x + (int)width, y + (int) height);
}
canvas.drawBitmap(bitmap, null, rect, null);
surface.unlockCanvasAndPost(canvas);
@Nullable
final DecoderCounters decoderCounters = BitmapFactoryVideoRenderer.this.decoderCounters;
if (decoderCounters != null) {
decoderCounters.renderedOutputBufferCount++;
}
if (!firstFrameRendered) {
firstFrameRendered = true;
eventDispatcher.renderedFirstFrame(surface);
}
}
/** /**
* *
* @return true if interrupted * @return true if interrupted
@ -210,9 +226,6 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
public void run() { public void run() {
final FormatHolder formatHolder = getFormatHolder(); final FormatHolder formatHolder = getFormatHolder();
@NonNull
final DecoderInputBuffer decoderInputBuffer =
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
long start = SystemClock.uptimeMillis(); long start = SystemClock.uptimeMillis();
main: main:
while (running) { while (running) {
@ -221,10 +234,8 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
formatHolder.format == null ? SampleStream.FLAG_REQUIRE_FORMAT : 0); formatHolder.format == null ? SampleStream.FLAG_REQUIRE_FORMAT : 0);
if (result == C.RESULT_BUFFER_READ) { if (result == C.RESULT_BUFFER_READ) {
if (decoderInputBuffer.isEndOfStream()) { if (decoderInputBuffer.isEndOfStream()) {
ended = true; //Wait for shutdown or stream to be changed
if (!sleep()) { sleep();
ended = false;
}
continue; continue;
} }
final long leadUs = decoderInputBuffer.timeUs - currentTimeUs; final long leadUs = decoderInputBuffer.timeUs - currentTimeUs;
@ -244,17 +255,17 @@ public class BitmapFactoryVideoRenderer extends BaseRenderer {
while (currentTimeUs < decoderInputBuffer.timeUs) { while (currentTimeUs < decoderInputBuffer.timeUs) {
//Log.d(TAG, "Sleep: us=" + currentTimeUs); //Log.d(TAG, "Sleep: us=" + currentTimeUs);
if (sleep()) { if (sleep()) {
//Sleep was interrupted, discard Bitmap
continue main; continue main;
} }
} }
if (running) { if (running) {
renderBitmap(bitmap, surface); renderBitmap(bitmap);
} }
} else if (result == C.RESULT_FORMAT_READ) { } else if (result == C.RESULT_FORMAT_READ) {
onFormatChanged(formatHolder); onFormatChanged(formatHolder);
} }
} }
ended = true;
} }
} }
} }