Android 为什么MediaPlayer.seekTo()和onSurfaceTextureUpdated()在循环中不起作用?

Android 为什么MediaPlayer.seekTo()和onSurfaceTextureUpdated()在循环中不起作用?,android,android-mediaplayer,video-capture,android-bitmap,textureview,Android,Android Mediaplayer,Video Capture,Android Bitmap,Textureview,我试图从textureview上的MediaPlayer视频中获取每100ms帧的屏幕截图(位图),位图的颜色配置应为ARGB_8888 我想每次我调用mediaplayer.seekTo(timeframe)时都会调用onSurfaceTextureUpdated,我可以在其中获取位图 因此,我在活动中创建了一个按钮,其中textureview并在活动中应用了单击方法,如下所示: public void onViewClicked() { float begin = starttim

我试图从textureview上的MediaPlayer视频中获取每100ms帧的屏幕截图(位图),位图的颜色配置应为ARGB_8888

我想每次我调用mediaplayer.seekTo(timeframe)时都会调用onSurfaceTextureUpdated,我可以在其中获取位图

因此,我在活动中创建了一个按钮,其中textureview并在活动中应用了单击方法,如下所示:

public void onViewClicked() {

    float begin = starttimeframe;  // starting point of analysis in timeframe
    float end = endtimeframe;      // ending point of analysis in timeframe

    int f = round(begin);
    status = 2;
    while (f < round(end)) {
        mediaplayer.seekTo(f);
        currenttimeframe = f;
        f += 100;  // forward to next frame (100ms interval)
    }

    Toast.makeText(Extractor2Activity.this, "Done!", Toast.LENGTH_SHORT).show();
}
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
            Bitmap bitmap = Bitmap.createBitmap(tvWidth, tvHeight, Bitmap.Config.ARGB_8888);
            textureView.getBitmap(bitmap);

            File file = new File(Environment.getExternalStorageDirectory().toString(), "capture" + current timeframe + ".jpg");

            OutputStream fout = null;
            try {
                fout = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
                fout.flush();
                fout.close();
                MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
问题是,textureview上的视频未更改,并且在迭代期间未调用OnSurfaceTextureUpdate

onSurfaceTextureUpdated()仅在显示Toast消息后调用一次

我想一定有解决办法,但我不擅长android编程,也不知道如何解决这个问题

如何使seekTo和OnSurfaceTextureUpdate在循环时正常工作

我所尝试的


使用MediaMetadataRetriever.getFrameAtTime,可以在循环中捕获所需的帧,但默认情况下获取的位图的颜色配置为RGB565,并且不知道如何从getFrameAtTime获取ARGB_8888 config的图像。

在这种情况下,一个小小的递归解决方案会很方便。您可以调用seek,等待回调,获取位图并进一步搜索。直到你到达小溪的尽头

public void onViewClicked() {

    viewClicked = true;

    seekTo(round(starttimeframe));
}

public void seekTo(int time) {
    if (time < round(endtimeframe)) {
        mediaplayer.seekTo(time);
        currenttimeframe = time;
    }
    else {
        viewClicked = false;
    }
}

public void onSurfaceTextureUpdated(SurfaceTexture surface) {
   if (viewClicked) {
        Bitmap bitmap = Bitmap.createBitmap(tvWidth, tvHeight, Bitmap.Config.ARGB_8888);
        textureView.getBitmap(bitmap);

        File file = new File(Environment.getExternalStorageDirectory().toString(), "capture" + current timeframe + ".jpg");

        OutputStream fout = null;
        try {
            fout = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
            fout.flush();
            fout.close();
            MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }
        seekTo(mediaPlayer.getCurrentPosition() + 100);
   }
}
public void onViewClicked(){
viewClicked=true;
seekTo(圆形(起始帧));
}
公共无效seekTo(整数时间){
if(时间<整轮(结束时间段)){
mediaplayer.seekTo(时间);
currenttimeframe=时间;
}
否则{
viewClicked=false;
}
}
已更新SurfaceTexture上的公共空间(SurfaceTexture surface){
如果(单击查看){
位图Bitmap=Bitmap.createBitmap(tvWidth、tvHeight、Bitmap.Config.ARGB_8888);
获取位图(位图);
File File=新文件(Environment.getExternalStorageDirectory().toString(),“capture”+当前时间段+“.jpg”);
OutputStream fout=null;
试一试{
fout=新文件输出流(文件);
压缩(bitmap.CompressFormat.JPEG,100,fout);
fout.flush();
fout.close();
MediaStore.Images.Media.insertImage(this.getContentResolver()、file.getAbsolutePath()、file.getName()、file.getName());
}捕获(IOE异常){
e、 printStackTrace();
}
seekTo(mediaPlayer.getCurrentPosition()+100);
}
}

等待帧缓冲,然后在每次调用
seekTo()
后进行渲染。@Abbas,感谢您的快速评论!你能给我一些示例代码吗?谢谢@Abbas!现在我知道如何解决这个问题了!