MediaPlayer在播放视频时会冻结

时间:2015-08-27 17:58:31

标签: android video media-player

我使用MediaPlayer播放适用于GPUImage效果的视频。在某些设备上,经过一段时间 - 几秒钟或更长时间(似乎是随机的),视频停止播放(图像仍然卡住),但音频一直在播放(大部分时间)。我将MediaPlayer定位到GLSurfaceView,以便能够在其上使用GPUImage效果。

以下是自定义视图:

public class FilteredVideoView extends GLSurfaceView {
private MediaPlayer mMediaPlayer = null;
private long time = 0;
private MyCustomRenderer renderer;
private boolean mediaPlayerInitialized = false;
private String videoPath;

public FilteredVideoView(Context context) {
    super(context);
    setWillNotDraw(false);
    init();
    //startFilterChangeThread();
}


public void setFilter(MyGPUImageFilter filter) {
    renderer.setFilter(filter);
}

public void stopVideo() {
    mMediaPlayer.stop();
}

public void prepareVideo() {
    try {
        mMediaPlayer.prepare();
    } catch (Exception e) {

    }
}

public void playVideo() {
    initMediaPlayer();

    mMediaPlayer.seekTo(0);
    mMediaPlayer.start();
}

private void init() {
    setEGLContextClientVersion(2);

    getHolder().setFormat(PixelFormat.TRANSLUCENT);
    setEGLConfigChooser(8, 8, 8, 8, 16, 0);

    mMediaPlayer = new MediaPlayer();

    //initMediaPlayer();

    renderer = new MyCustomRenderer(new MyNoFilterFilter(), mMediaPlayer);
    setRenderer(renderer);
}

private void initMediaPlayer() {
    if (mediaPlayerInitialized) {
        return;
    }

    mediaPlayerInitialized = true;

    try {
        FileInputStream fi = new FileInputStream(new File(videoPath));

        mMediaPlayer.setDataSource(fi.getFD());
        mMediaPlayer.prepare();

        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                onVideoPlaybackFinished();
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }

}

void onVideoPlaybackFinished() {

}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();

    if (mMediaPlayer != null) {
        mMediaPlayer.stop();
        mMediaPlayer.release();
    }
}

这是渲染器。

public class MyCustomRenderer implements Renderer, SurfaceTexture.OnFrameAvailableListener {
public static final int NO_IMAGE = -1;
public static final float CUBE[] = {
        -1.0f, -1.0f,
        1.0f, -1.0f,
        -1.0f, 1.0f,
        1.0f, 1.0f,
};

private MyGPUImageFilter mFilter;

public final Object mSurfaceChangedWaiter = new Object();

private int mTextureID = NO_IMAGE;
private SurfaceTexture mSurfaceTexture = null;
private final FloatBuffer mGLCubeBuffer;
private final FloatBuffer mGLTextureBuffer;
private IntBuffer mGLRgbBuffer;

private int mOutputWidth;
private int mOutputHeight;
private int mImageWidth;
private int mImageHeight;
private int mAddedPadding;

private final Queue<Runnable> mRunOnDraw;
private final Queue<Runnable> mRunOnDrawEnd;
private Rotation mRotation;
private boolean mFlipHorizontal;
private boolean mFlipVertical;
private GPUImage.ScaleType mScaleType = GPUImage.ScaleType.CENTER_CROP;

public SurfaceTexture mSurface;
public boolean updateSurface = false;
private MediaPlayer mMediaPlayer;
private int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
private float[] mSTMatrix = new float[16];

public MyCustomRenderer(final MyGPUImageFilter filter, MediaPlayer mediaPlayer) {
    mMediaPlayer = mediaPlayer;
    mFilter = filter;
    mRunOnDraw = new LinkedList<Runnable>();
    mRunOnDrawEnd = new LinkedList<Runnable>();

    mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();
    mGLCubeBuffer.put(CUBE).position(0);

    mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();
    setRotation(Rotation.NORMAL, false, false);

    Matrix.setIdentityM(mSTMatrix, 0);
}

@Override
public void onSurfaceCreated(final GL10 unused, final EGLConfig config) {
    int[] textures = new int[1];
    GLES20.glGenTextures(1, textures, 0);

    mTextureID = textures[0];
    GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);

    mSurface = new SurfaceTexture(mTextureID);
    mSurface.setOnFrameAvailableListener(this);

    Surface surface = new Surface(mSurface);

    mMediaPlayer.setSurface(surface);
    surface.release();

    synchronized (this) {
        updateSurface = false;
    }


    GLES20.glClearColor(0, 0, 0, 1);
    GLES20.glDisable(GLES20.GL_DEPTH_TEST);

    mFilter.init();
    //mMediaPlayer.start();
}

@Override
public void onSurfaceChanged(final GL10 gl, final int width, final int height) {
    mOutputWidth = width;
    mOutputHeight = height;
    GLES20.glViewport(0, 0, width, height);
    GLES20.glUseProgram(mFilter.getProgram());
    mFilter.onOutputSizeChanged(width, height);
    adjustImageScaling();
    synchronized (mSurfaceChangedWaiter) {
        mSurfaceChangedWaiter.notifyAll();
    }
}

@Override
public void onDrawFrame(final GL10 gl) {
    synchronized (this) {
        if (updateSurface) {
            mSurface.updateTexImage();
            mSurface.getTransformMatrix(mSTMatrix);
            updateSurface = false;
        } else {
            //return;
        }
    }

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    runAll(mRunOnDraw);
    mFilter.onDraw(mTextureID, mGLCubeBuffer, mGLTextureBuffer);
    runAll(mRunOnDrawEnd);

    /*if (mSurfaceTexture != null) {
        mSurfaceTexture.updateTexImage();
    }*/



}

private void runAll(Queue<Runnable> queue) {
    synchronized (queue) {
        while (!queue.isEmpty()) {
            queue.poll().run();
        }
    }
}


public void setFilter(final MyGPUImageFilter filter) {
    runOnDraw(new Runnable() {

        @Override
        public void run() {
            final MyGPUImageFilter oldFilter = mFilter;
            mFilter = filter;
            if (oldFilter != null) {
                oldFilter.destroy();
            }
            mFilter.init();
            GLES20.glUseProgram(mFilter.getProgram());
            mFilter.onOutputSizeChanged(mOutputWidth, mOutputHeight);
        }
    });
}

public void deleteImage() {
    runOnDraw(new Runnable() {

        @Override
        public void run() {
            GLES20.glDeleteTextures(1, new int[]{
                    mTextureID
            }, 0);
            mTextureID = NO_IMAGE;
        }
    });
}

public void setScaleType(GPUImage.ScaleType scaleType) {
    mScaleType = scaleType;
}

protected int getFrameWidth() {
    return mOutputWidth;
}

protected int getFrameHeight() {
    return mOutputHeight;
}

private void adjustImageScaling() {
    float outputWidth = mOutputWidth;
    float outputHeight = mOutputHeight;


    if (mRotation == Rotation.ROTATION_270 || mRotation == Rotation.ROTATION_90) {
        outputWidth = mOutputHeight;
        outputHeight = mOutputWidth;
    }

    mImageWidth = App.screenW();
    mImageHeight = App.screenH();

    outputWidth = App.screenW();
    outputHeight = App.screenH();

    float ratio1 = outputWidth / mImageWidth;
    float ratio2 = outputHeight / mImageHeight;
    float ratioMax = Math.max(ratio1, ratio2);
    int imageWidthNew = Math.round(mImageWidth * ratioMax);
    int imageHeightNew = Math.round(mImageHeight * ratioMax);

    float ratioWidth = imageWidthNew / outputWidth;
    float ratioHeight = imageHeightNew / outputHeight;

    float[] cube = CUBE;
    float[] textureCords = TextureRotationUtil.getRotation(mRotation, mFlipHorizontal, mFlipVertical);
    if (mScaleType == GPUImage.ScaleType.CENTER_CROP) {
        float distHorizontal = (1 - 1 / ratioWidth) / 2;
        float distVertical = (1 - 1 / ratioHeight) / 2;
        textureCords = new float[]{
                addDistance(textureCords[0], distHorizontal), addDistance(textureCords[1], distVertical),
                addDistance(textureCords[2], distHorizontal), addDistance(textureCords[3], distVertical),
                addDistance(textureCords[4], distHorizontal), addDistance(textureCords[5], distVertical),
                addDistance(textureCords[6], distHorizontal), addDistance(textureCords[7], distVertical),
        };
    } else {
        cube = new float[]{
                CUBE[0] / ratioHeight, CUBE[1] / ratioWidth,
                CUBE[2] / ratioHeight, CUBE[3] / ratioWidth,
                CUBE[4] / ratioHeight, CUBE[5] / ratioWidth,
                CUBE[6] / ratioHeight, CUBE[7] / ratioWidth,
        };
    }

    mGLCubeBuffer.clear();
    mGLCubeBuffer.put(cube).position(0);
    mGLTextureBuffer.clear();
    mGLTextureBuffer.put(textureCords).position(0);
}

private float addDistance(float coordinate, float distance) {
    return coordinate == 0.0f ? distance : 1 - distance;
}

public void setRotationCamera(final Rotation rotation, final boolean flipHorizontal,
                              final boolean flipVertical) {
    setRotation(rotation, flipVertical, flipHorizontal);
}

public void setRotation(final Rotation rotation) {
    mRotation = rotation;
    adjustImageScaling();
}

public void setRotation(final Rotation rotation,
                        final boolean flipHorizontal, final boolean flipVertical) {
    mFlipHorizontal = flipHorizontal;
    mFlipVertical = flipVertical;
    setRotation(rotation);
}

public Rotation getRotation() {
    return mRotation;
}

public boolean isFlippedHorizontally() {
    return mFlipHorizontal;
}

public boolean isFlippedVertically() {
    return mFlipVertical;
}

protected void runOnDraw(final Runnable runnable) {
    synchronized (mRunOnDraw) {
        mRunOnDraw.add(runnable);
    }
}

protected void runOnDrawEnd(final Runnable runnable) {
    synchronized (mRunOnDrawEnd) {
        mRunOnDrawEnd.add(runnable);
    }
}

@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
    updateSurface = true;
}
}

任何可能导致问题的想法?也许是内存泄漏?

感谢您的帮助!

0 个答案:

没有答案