Skip to content

Commit 65abbe5

Browse files
Saqragnatario1
authored andcommitted
New drop frame algorithm (deepmedia#9)
* new drop frame algo * fix inverting true and false in function shouldRenderFrame() * fix null pointer exception when use PassThroughTrackStrategy
1 parent 47395ab commit 65abbe5

File tree

2 files changed

+31
-38
lines changed

2 files changed

+31
-38
lines changed

lib/src/main/java/com/otaliastudios/transcoder/transcode/PassThroughTrackTranscoder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class PassThroughTrackTranscoder implements TrackTranscoder {
3838
private ByteBuffer mBuffer;
3939
private boolean mIsEOS;
4040
private long mWrittenPresentationTimeUs;
41+
private final MediaFormat mActualOutputFormat;
42+
private boolean mFirstStepPipeline = true;
4143

4244
public PassThroughTrackTranscoder(@NonNull MediaExtractor extractor,
4345
int trackIndex,
@@ -48,8 +50,7 @@ public PassThroughTrackTranscoder(@NonNull MediaExtractor extractor,
4850
mMuxer = muxer;
4951
mTrackType = trackType;
5052

51-
MediaFormat mActualOutputFormat = mExtractor.getTrackFormat(mTrackIndex);
52-
mMuxer.setOutputFormat(mTrackType, mActualOutputFormat);
53+
mActualOutputFormat = mExtractor.getTrackFormat(mTrackIndex);
5354
mBufferSize = mActualOutputFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
5455
mBuffer = ByteBuffer.allocateDirect(mBufferSize).order(ByteOrder.nativeOrder());
5556
}
@@ -62,6 +63,10 @@ public void setUp(@NonNull MediaFormat desiredOutputFormat) {
6263
@Override
6364
public boolean stepPipeline() {
6465
if (mIsEOS) return false;
66+
if (mFirstStepPipeline) {
67+
mMuxer.setOutputFormat(mTrackType, mActualOutputFormat);
68+
mFirstStepPipeline = false;
69+
}
6570
int trackIndex = mExtractor.getSampleTrackIndex();
6671
if (trackIndex < 0) {
6772
mBuffer.clear();

lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,9 @@ public class VideoTrackTranscoder implements TrackTranscoder {
6161
private VideoDecoderOutput mDecoderOutputSurface;
6262
private VideoEncoderInput mEncoderInputSurface;
6363

64-
// A step is defined as the microseconds between two frame.
65-
// The average step is basically 1 / frame rate.
66-
private float mAvgStep = 0;
67-
private float mTargetAvgStep;
68-
private int mRenderedSteps = -1; // frames - 1
69-
private long mLastRenderedUs;
70-
private long mLastStep;
64+
private double mInFrameRateReciprocal;
65+
private double mOutFrameRateReciprocal;
66+
private double mFrameRateReciprocalSum;
7167

7268
public VideoTrackTranscoder(
7369
@NonNull MediaExtractor extractor,
@@ -82,8 +78,12 @@ public VideoTrackTranscoder(
8278
public void setUp(@NonNull MediaFormat desiredOutputFormat) {
8379
mExtractor.selectTrack(mTrackIndex);
8480

85-
int frameRate = desiredOutputFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
86-
mTargetAvgStep = (1F / frameRate) * 1000 * 1000;
81+
MediaFormat trackFormat = mExtractor.getTrackFormat(mTrackIndex);
82+
int inFrameRate = trackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
83+
int outFrameRate = desiredOutputFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
84+
mInFrameRateReciprocal = 1.0d / inFrameRate;
85+
mOutFrameRateReciprocal = 1.0d / outFrameRate;
86+
LOG.v("mInFrameRateReciprocal: " + mInFrameRateReciprocal + " mOutFrameRateReciprocal: " + mOutFrameRateReciprocal);
8787

8888
// Configure encoder.
8989
try {
@@ -228,37 +228,25 @@ private int drainDecoder(long timeoutUs) {
228228
return DRAIN_STATE_CONSUMED;
229229
}
230230

231-
// TODO improve this. as it is now, rendering a frame after dropping many,
232-
// will not decrease avgStep but rather increase it (for this single frame; then it starts decreasing).
233-
// This has the effect that, when a frame is rendered, the following frame is always rendered,
234-
// because the conditions are worse then before. After this second frame things go back to normal,
235-
// but this is terrible logic.
231+
//Refer:https://stackoverflow.com/questions/4223766/dropping-video-frames
236232
private boolean shouldRenderFrame() {
237233
if (mBufferInfo.size <= 0) return false;
238-
if (mRenderedSteps > 0 && mAvgStep < mTargetAvgStep) {
239-
// We are rendering too much. Drop this frame.
240-
// Always render first 2 frames, we need them to compute the avg.
241-
LOG.v("FRAME: Dropping. avg: " + mAvgStep + " target: " + mTargetAvgStep);
242-
long newLastStep = mBufferInfo.presentationTimeUs - mLastRenderedUs;
243-
float allSteps = (mAvgStep * mRenderedSteps) - mLastStep + newLastStep;
244-
mAvgStep = allSteps / mRenderedSteps; // we didn't add a step, just increased the last
245-
mLastStep = newLastStep;
246-
return false;
247-
} else {
248-
// Render this frame, since our average step is too long or exact.
249-
LOG.v("FRAME: RENDERING. avg: " + mAvgStep + " target: " + mTargetAvgStep + "New stepCount: " + (mRenderedSteps + 1));
250-
if (mRenderedSteps >= 0) {
251-
// Update the average value, since now we have mLastRenderedUs.
252-
long step = mBufferInfo.presentationTimeUs - mLastRenderedUs;
253-
float allSteps = (mAvgStep * mRenderedSteps) + step;
254-
mAvgStep = allSteps / (mRenderedSteps + 1); // we added a step, so +1
255-
mLastStep = step;
256-
}
257-
// Increment both
258-
mRenderedSteps++;
259-
mLastRenderedUs = mBufferInfo.presentationTimeUs;
234+
boolean firstFrame = Double.valueOf(0d).equals(mFrameRateReciprocalSum);
235+
mFrameRateReciprocalSum += mInFrameRateReciprocal;
236+
if (firstFrame) {
237+
// render frame
238+
LOG.v("render this frame -> mFrameRateReciprocalSum: " + mFrameRateReciprocalSum);
260239
return true;
261240
}
241+
if (mFrameRateReciprocalSum > mOutFrameRateReciprocal) {
242+
mFrameRateReciprocalSum -= mOutFrameRateReciprocal;
243+
// render frame
244+
LOG.v("render this frame -> mFrameRateReciprocalSum: " + mFrameRateReciprocalSum);
245+
return true;
246+
}
247+
// drop frame
248+
LOG.v("drop this frame -> mFrameRateReciprocalSum: " + mFrameRateReciprocalSum);
249+
return false;
262250
}
263251

264252
@SuppressWarnings("SameParameterValue")

0 commit comments

Comments
 (0)