Cla*_*ssA 17 android mediacodec android-mediacodec
这是一个很长的问题,但我必须解释我正在经历的问题才能正确地解决问题.希望我能找到像@fadden或@mstorsjo这样的人来看看这个问题.
有关此问题的最新更新,请参阅编辑3.
我目前正在快速精确地寻求使用MediaCodec
.我目前要逐帧跳过的是,我首先得到总帧数:
mediaInfo.totalFrames = videoTrack.getSamples().size();
Run Code Online (Sandbox Code Playgroud)
然后我得到视频文件的长度:
mediaInfo.durationUs = videoTrack.getDuration() * 1000 *1000 / timeScale;
//then calling:
public long getDuration() {
if (mMediaInfo != null) {
return (int) mMediaInfo.durationUs / 1000; // to millisecond
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
现在,当我想要获得下一帧时,我会调用以下内容:
mNextFrame.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int frames = Integer.parseInt(String.valueOf(getTotalFrames));
int intervals = Integer.parseInt(String.valueOf(mPlayer.getDuration() / frames));
if (mPlayer.isPlaying()) {
mPlayer.pause();
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
} else {
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
}
}
});
Run Code Online (Sandbox Code Playgroud)
以下是我正在测试的文件的信息:
Frames = 466
Duration = 15523
所以帧之间的间隔是
33,311158798283262
换句话说,每当我按下下一个按钮时,间隔将四舍五入到33
,当我按下下一个按钮时,它将调用mPlayer.seekTo(mPlayer.getCurrentPosition() + 33
意味着某些帧将丢失,或者这就是我的想法.我getCurrentPosition
在每次按下按钮后进行测试时测试并得到以下信息,结果如下:
33 -> 66 -> 99 -> 132 -> 166
从那里132
开始166
是34毫秒而不是33毫秒,所以有补偿来弥补可能丢失的帧.
以上工作完全没问题,我可以跳过框架没有任何问题,这是我面临的问题.
采用我上面使用的相同逻辑,我创建了一个自定义RangeBar
.我创建了一个方法setTickCount
(它基本上是相同的seekbar.setMax
),我设置了"TickCount",如下所示:
int frames = Integer.parseInt(String.valueOf(getTotalFrames));
mrange_bar.setTickCount(frames);
Run Code Online (Sandbox Code Playgroud)
所以我的最大值RangeBar
是视频中的帧数.
当"Tick"值改变时,我调用以下内容:
int frames = Integer.parseInt(String.valueOf(getTotalFrames));
int intervals = Integer.parseInt(String.valueOf(mPlayer.getDuration() / frames));
mPlayer.seekTo(intervals * TickPosition);
Run Code Online (Sandbox Code Playgroud)
所以上面的内容会这样,如果我的tickCount位置是,那就说40:
mPlayer.seekTo(33 * 40); //1320ms
我认为上面的工作正常,因为我使用完全相同的逻辑,而是视频"跳/跳"回到(我假设是关键帧)并继续寻找.
有人可以向我解释为什么会发生这种情况以及如何解决这个问题?
我上面提到过,它跳到了前一个关键帧,但我又看了一眼,它在搜索时调用了流的结尾(在视频期间的特定点).当我到达流的末尾时,我释放了我之前的缓冲区,以便通过调用以下方式仍然可以显示一帧以避免黑屏:
mDecoder.releaseOutputBuffer(prevBufferIndex, true);
所以,由于某种原因,调用了流的结束,然后我重新启动mediacodec,导致"滞后/跳跃"效果.如果我删除上面的内容,我不会让帧"跳",但是在初始化mediacodec时仍然存在延迟.
在深入挖掘之后,我发现它readSampleData
是-1:
ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
int inIndex = mDecoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize = mExtractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
mDecoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
mIsExtractorReachedEOS = true;
} else {
mDecoder.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
mExtractor.advance();
}
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,我sampleSize
在寻找期间的特定点是-1.
这个问题肯定是关于我通过的时间,我尝试了两种不同的方法,第一种:
mPlayer.seekTo(progress);
//position is retrieved by setting mSeekBar.setMax(mPlayer.getDuration); ....
Run Code Online (Sandbox Code Playgroud)
和第二种方法,我确定帧间隔:
//Total amount of frames in video
long TotalFramesInVideo = videoTrack.getSamples().size();
//Duration of file in milliseconds
int DurationOfVideoInMs = mPlayer.getDuration();
//Determine interval between frames
int frameIntervals = DurationOfVideoInMs / Integer.parseInt(String.valueOf(TotalFramesInVideo));
//Then I seek to the frames like this:
mPlayer.seekTo(position * frameIntervals);
Run Code Online (Sandbox Code Playgroud)
在尝试了上述两种方法后,我意识到问题与传递给mediaCodec的时间有关,因为"滞后/跳跃"发生在不同的地方.
我不确定为什么在我打电话时不会发生这种情况:
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
554 次 |
最近记录: |