mirror of
https://github.com/samsonjs/media.git
synced 2026-04-07 11:35:46 +00:00
Fix transcoding drops a few frames.
In the old version, the transcoder uses decoder.isEnded() alone as the criteria to stop the encoding/muxing process. It's rectified to: - On decoder ending, signal the encoder of EOS after writing all decoded frames to it. - On encoder ending, write end track to muxer. PiperOrigin-RevId: 393322114
This commit is contained in:
parent
9c2b4b860b
commit
58e5ed0afb
6 changed files with 45 additions and 5 deletions
|
|
@ -303,6 +303,11 @@ import java.nio.ByteBuffer;
|
|||
codec.setVideoScalingMode(scalingMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signalEndOfInputStream() {
|
||||
codec.signalEndOfInputStream();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
/* package */ void onError(MediaCodec.CodecException error) {
|
||||
asynchronousMediaCodecCallback.onError(codec, error);
|
||||
|
|
|
|||
|
|
@ -242,4 +242,13 @@ public interface MediaCodecAdapter {
|
|||
|
||||
/** Whether the adapter needs to be reconfigured before it is used. */
|
||||
boolean needsReconfiguration();
|
||||
|
||||
/**
|
||||
* Signals the encoder of end-of-stream on input. The call can only be used when the encoder
|
||||
* receives its input from a {@link Surface surface}.
|
||||
*
|
||||
* @see MediaCodec#signalEndOfInputStream()
|
||||
*/
|
||||
@RequiresApi(18)
|
||||
void signalEndOfInputStream();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,6 +199,12 @@ public class SynchronousMediaCodecAdapter implements MediaCodecAdapter {
|
|||
codec.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresApi(18)
|
||||
public void signalEndOfInputStream() {
|
||||
Api18.signalEndOfInputStream(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresApi(23)
|
||||
public void setOnFrameRenderedListener(OnFrameRenderedListener listener, Handler handler) {
|
||||
|
|
@ -232,5 +238,10 @@ public class SynchronousMediaCodecAdapter implements MediaCodecAdapter {
|
|||
public static Surface createCodecInputSurface(MediaCodec codec) {
|
||||
return codec.createInputSurface();
|
||||
}
|
||||
|
||||
@DoNotInline
|
||||
public static void signalEndOfInputStream(MediaCodec codec) {
|
||||
codec.signalEndOfInputStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,6 +311,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
inputBuffer.data = null;
|
||||
}
|
||||
|
||||
@RequiresApi(18)
|
||||
public void signalEndOfInputStream() {
|
||||
codec.signalEndOfInputStream();
|
||||
}
|
||||
|
||||
/** Returns the current output format, if available. */
|
||||
@Nullable
|
||||
public Format getOutputFormat() {
|
||||
|
|
|
|||
|
|
@ -175,8 +175,15 @@ import java.nio.ByteBuffer;
|
|||
if (decoder.isEnded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rendering the decoder output queues input to the encoder because they share the same surface.
|
||||
return decoder.maybeDequeueRenderAndReleaseOutputBuffer();
|
||||
boolean hasProcessedOutputBuffer = decoder.maybeDequeueRenderAndReleaseOutputBuffer();
|
||||
if (decoder.isEnded()) {
|
||||
checkNotNull(encoder).signalEndOfInputStream();
|
||||
// All decoded frames have been rendered to the encoder's input surface.
|
||||
return false;
|
||||
}
|
||||
return hasProcessedOutputBuffer;
|
||||
}
|
||||
|
||||
private boolean feedMuxerFromEncoder() {
|
||||
|
|
@ -190,10 +197,7 @@ import java.nio.ByteBuffer;
|
|||
muxerWrapper.addTrackFormat(encoderOutputFormat);
|
||||
}
|
||||
|
||||
// TODO(claincly) May have to use inputStreamBuffer.isEndOfStream result to call
|
||||
// decoder.signalEndOfInputStream().
|
||||
MediaCodecAdapterWrapper decoder = checkNotNull(this.decoder);
|
||||
if (decoder.isEnded()) {
|
||||
if (encoder.isEnded()) {
|
||||
muxerWrapper.endTrack(getTrackType());
|
||||
muxerWrapperTrackEnded = true;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -268,6 +268,12 @@ public class CapturingRenderersFactory implements RenderersFactory, Dumper.Dumpa
|
|||
delegate.setVideoScalingMode(scalingMode);
|
||||
}
|
||||
|
||||
@RequiresApi(18)
|
||||
@Override
|
||||
public void signalEndOfInputStream() {
|
||||
delegate.signalEndOfInputStream();
|
||||
}
|
||||
|
||||
// Dumpable implementation
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in a new issue