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

Why MediaPlayer.seekTo() and onSurfaceTextureUpdated() not working inside loop?

我正在尝试从 textureview 上的 MediaPlayer 视频中获取每 100 毫秒帧的屏幕截图(位图),位图的颜色配置应该是 ARGB_8888

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

所以我在 activity 中创建了一个按钮,其中 textureview 并在 activity 中应用了点击方法,如下所示:

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();
}

并添加了当 surfacetexture 像这样更新时捕获 textureview 的代码:

    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 上的视频没有改变,并且在迭代期间没有调用 onSurfaceTextureUpdated。

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

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

如何让seekTo和onSurfaceTextureUpdated在循环时正常工作?

我试过的:

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

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

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);
   }
}