所以我写了一个视频播放库,细节并不重要。发生了什么是这段代码需要在解码器线程的run()方法结束时运行:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
问题是,任何事都没有通过do {}而没有执行。这是一个奇怪的部分,当在while循环中添加System.out.println时执行这段代码:
System.out.println("Video decoding complete");
int a = 0, b = 0;
do
{
System.out.println("Waiting for packets to drain.");
a = pictures.getCount();
b = samples.getCount();
}while(a > 0 || b > 0);
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
我怀疑编译器知道我试图让它运行一个循环什么都不做,它只是剪掉代码或其他东西。但实际上我不知道发生了什么。如果有人比我更了解,我很乐意找到更好的解决方案。我在这里挂了这么简单的事情!
答案 0 :(得分:4)
我的猜测是pictures.getCount()和samples.getCount()读取非volatile
字段。当您只读取一个非易失性字段时,可以出于性能原因进行内联,但是如果您执行类似调用synchronized
方法(并且System.out已同步)的操作,则不会以这种方式优化代码并且每次都要进行查找。
我建议您尝试添加一个空的同步块,看看这是否仍然有效,即执行此操作而不是println
synchronized(this) { }
答案 1 :(得分:0)
根据@ slim的建议,我最终做到了这一点:
System.out.println("Video decoding complete");
this.decoderComplete = true;
//wait until notified that packets are done draining
synchronized(this)
{
try {
this.wait();
} catch (InterruptedException e) {
videoComplete = true;
this.container.close();
e.printStackTrace();
}
}
Gdx.app.log("Status", videoPath + " completed playing successfully.");
videoComplete = true;
this.container.close();
在另一个帖子中,一旦我们知道我们已经读完了所有数据包:
if(this.packetHandlerRunnable.getNumAudioPackets() <= 0
&& this.packetHandlerRunnable.getNumVideoPackets() <= 0
&& this.packetHandlerRunnable.isDecoderComplete())
{
synchronized(packetHandlerRunnable)
{
this.packetHandlerRunnable.notify();
}
}