请教:Android正播放视频时的解码输出流如何获取?

鱼儿_飞吧 2014-08-19 12:01:03
加精
Android播放视频,经过解码器解码 获得数据流 再显示到屏幕上。请问这部分数据(解码器解码后的数据流)通过什么方法可以获取? 请教。。。 先谢谢啦
...全文
10756 74 打赏 收藏 转发到动态 举报
写回复
用AI写文章
74 条回复
切换为时间正序
请发表友善的回复…
发表回复
鱼儿_飞吧 2016-11-29
  • 打赏
  • 举报
回复
这个问题过去了这么久,最近发现也有不少朋友遇到类似问题,再补充说明一下, 当时使用SurfaceTexture播放不出来东西 是因为我调试用的机器不支持,换用其他型号手机或平板正常显示,耽误好久找错误找方案。。。太疏忽了,SurfaceTexture就可以搞定,代码也没有问题~ 就是在使用前记得检查硬件
stone_fly_K 2015-11-23
  • 打赏
  • 举报
回复
楼主解决了吗?能不能给个demo,最近也在弄着个!!! 707196165@qq.com
千斤神力王 2015-08-10
  • 打赏
  • 举报
回复
引用 71 楼 YKDSea 的回复:
[quote=引用 70 楼 princeop2010 的回复:] [quote=引用 47 楼 YKDSea 的回复:] [quote=引用 45 楼 yu8fei 的回复:] [quote=引用 44 楼 YKDSea 的回复:] [quote=引用 42 楼 yu8fei 的回复:] 错了错了,弄混乱了有点, 上面那个不是“读取camera图像流的例子”,是另外的一个 SurfaceTexture测试video用的, createProgram对应的俩个参数就是上面的两个字符串,求大神帮忙解释说明下,应该从哪里着手
camera里面有个api,setPreviewTexture来接收surfacetexture,但是mediaplayer没有这样的api的。[/quote]能使用SurfaceTexture代替SurfaceView来显示,播放电影应该就可以了吧,能做到吗这样?SurfaceTexture不会用也没有api,google打不开!![/quote] 下午看了下Surface的api,有个途径可以试下,写一个类似下面的class

public class LocalHolder  implements  SurfaceHolder{
	SurfaceTexture m_st;
	Surface m_surface;
	LocalHolder(SurfaceTexture st){
		m_st = st;
		m_surface = new Suface(m_st);
	}
	@Override
        public Surface getSurface() {
            return m_surface;
        }

	....//其他接口还需要补全
}
这样,你建立一个SurfaceTexture初始化后传给用这个texture构造一个LocalHolder出来, 然后Mediaplayer.setDisplay就传入LocalHolder对象。[/quote] 卡卡西你真是大神,我最近想要实现一个后台录像,也是急得不行,烦死了,现在在考虑怎么调用摄像头然后直接从摄像头获取数据,不让它preview了。[/quote] 你这个不难的,不能用surfaceview(到后台后surface会摧毁),surfacetexture就可以了。 有不少监控软件都是这么做的,在前台能显示,到后台还能继续监控。[/quote] 谢谢大神!
sky-Z 2015-08-09
  • 打赏
  • 举报
回复
引用 70 楼 princeop2010 的回复:
[quote=引用 47 楼 YKDSea 的回复:] [quote=引用 45 楼 yu8fei 的回复:] [quote=引用 44 楼 YKDSea 的回复:] [quote=引用 42 楼 yu8fei 的回复:] 错了错了,弄混乱了有点, 上面那个不是“读取camera图像流的例子”,是另外的一个 SurfaceTexture测试video用的, createProgram对应的俩个参数就是上面的两个字符串,求大神帮忙解释说明下,应该从哪里着手
camera里面有个api,setPreviewTexture来接收surfacetexture,但是mediaplayer没有这样的api的。[/quote]能使用SurfaceTexture代替SurfaceView来显示,播放电影应该就可以了吧,能做到吗这样?SurfaceTexture不会用也没有api,google打不开!![/quote] 下午看了下Surface的api,有个途径可以试下,写一个类似下面的class

public class LocalHolder  implements  SurfaceHolder{
	SurfaceTexture m_st;
	Surface m_surface;
	LocalHolder(SurfaceTexture st){
		m_st = st;
		m_surface = new Suface(m_st);
	}
	@Override
        public Surface getSurface() {
            return m_surface;
        }

	....//其他接口还需要补全
}
这样,你建立一个SurfaceTexture初始化后传给用这个texture构造一个LocalHolder出来, 然后Mediaplayer.setDisplay就传入LocalHolder对象。[/quote] 卡卡西你真是大神,我最近想要实现一个后台录像,也是急得不行,烦死了,现在在考虑怎么调用摄像头然后直接从摄像头获取数据,不让它preview了。[/quote] 你这个不难的,不能用surfaceview(到后台后surface会摧毁),surfacetexture就可以了。 有不少监控软件都是这么做的,在前台能显示,到后台还能继续监控。
千斤神力王 2015-08-07
  • 打赏
  • 举报
回复
引用 47 楼 YKDSea 的回复:
[quote=引用 45 楼 yu8fei 的回复:] [quote=引用 44 楼 YKDSea 的回复:] [quote=引用 42 楼 yu8fei 的回复:] 错了错了,弄混乱了有点, 上面那个不是“读取camera图像流的例子”,是另外的一个 SurfaceTexture测试video用的, createProgram对应的俩个参数就是上面的两个字符串,求大神帮忙解释说明下,应该从哪里着手
camera里面有个api,setPreviewTexture来接收surfacetexture,但是mediaplayer没有这样的api的。[/quote]能使用SurfaceTexture代替SurfaceView来显示,播放电影应该就可以了吧,能做到吗这样?SurfaceTexture不会用也没有api,google打不开!![/quote] 下午看了下Surface的api,有个途径可以试下,写一个类似下面的class

public class LocalHolder  implements  SurfaceHolder{
	SurfaceTexture m_st;
	Surface m_surface;
	LocalHolder(SurfaceTexture st){
		m_st = st;
		m_surface = new Suface(m_st);
	}
	@Override
        public Surface getSurface() {
            return m_surface;
        }

	....//其他接口还需要补全
}
这样,你建立一个SurfaceTexture初始化后传给用这个texture构造一个LocalHolder出来, 然后Mediaplayer.setDisplay就传入LocalHolder对象。[/quote] 卡卡西你真是大神,我最近想要实现一个后台录像,也是急得不行,烦死了,现在在考虑怎么调用摄像头然后直接从摄像头获取数据,不让它preview了。
真实的数字 2015-08-03
  • 打赏
  • 举报
回复
我这两天正在研究这个事情 完全没有头绪啊 用的ffmpeg 获得了 rbg的流 可是要怎么播放呢 楼主有没有好的思路
鱼儿_飞吧 2014-09-28
  • 打赏
  • 举报
回复
SurfaceTexture可以用,但是没做成功。参考另外一种方法,提取解码的部分修改成自己的需求再次编译成动态库,导入项目中使用。参考github:https://github.com/bbcallen/ijkplayer.git
鱼儿_飞吧 2014-08-27
  • 打赏
  • 举报
回复
引用 66 楼 Aisy_D 的回复:
呵呵呵..... 一般android的显示一般有两层(或者两层以上), fb0, 和 fb1, fb1 在 fb0 的下面, fb1 显示软件的界面, fb0 平时一般是透明的, 在播放视频 的时候, 如果视频使用硬件解码, 解码后的 YUV 图像帧 直接 memcpy 到 fb0 的 framebuffer中, 这时候你就可以看到视频了, 中间不经过任何JAVA代码, 如果不是全屏, 那么fb0的只有视频区域的 alpha值 为 255, 其它区域为0, 使得后面的界面可以透上来... 你要抓 解码后的数据, 从GPU的驱动下手, HOOK一个接口出来可能有希望......
SurfaceTexture API有这么句话“The image stream may come from either camera preview or video decode.” the image stream from video decode 就够了,想办法实现就OK,你这个思路 这边行不通再说吧
sky-Z 2014-08-26
  • 打赏
  • 举报
回复
引用 59 楼 yu8fei 的回复:
引用 58 楼 YKDSea 的回复:
引用 57 楼 yu8fei 的回复:
引用 56 楼 YKDSea 的回复:
引用 54 楼 yu8fei 的回复:
引用 53 楼 YKDSea 的回复:
写错了,应该是”surfaceTexture.java里面的成员mSurfaceTexture,他是int类型,实际是一个指向native层的GLConsumer对象的指针。“这些在android代码里面都有的,不要光看api,往下看看实现。
mTextureID是int类型的,mSurfaceTexture是SurfaceTexture类型的
你看的哪个文件?我说的是class SurfaceTexture里面。
鱼儿_飞吧 2014-08-26
  • 打赏
  • 举报
回复
引用 58 楼 YKDSea 的回复:
引用 57 楼 yu8fei 的回复:
引用 56 楼 YKDSea 的回复:
引用 54 楼 yu8fei 的回复:
引用 53 楼 YKDSea 的回复:
写错了,应该是”surfaceTexture.java里面的成员mSurfaceTexture,他是int类型,实际是一个指向native层的GLConsumer对象的指针。“这些在android代码里面都有的,不要光看api,往下看看实现。
mTextureID是int类型的,mSurfaceTexture是SurfaceTexture类型的
sky-Z 2014-08-26
  • 打赏
  • 举报
回复
引用 57 楼 yu8fei 的回复:
引用 56 楼 YKDSea 的回复:
[quote=引用 54 楼 yu8fei 的回复:] [quote=引用 53 楼 YKDSea 的回复:] 不知道你是怎么理解的,onFrameAvailable是回调函数,有新数据来的时候,才会被调用,不是看调用的参数。
是不知道怎么用。播放视频的时候数据流是有更新的,它就会一直被调用的,如果要进行数据处理,应该就是在这进行。 视频正播放的时候无画面输出,只有声音。 如果我要取出SurfaceTexture中的数据应该怎么取呢?
到jni层去操作就好做了,surfaceTexture.java里面的mSurfaceTexture分别对应了GLConsumer。 新的frame来的时候,先调用SurfaceTexture.updateTexImage()更新一下buffer,然后GLConsumer.getCurrentBuffer()可以拿到GraphicBuffer了,GraphicBuffer.lock()又可以直接拿到指针了。要注意color format。[/quote]不理解你这句话“surfaceTexture.java里面的mSurfaceTexture分别对应了GLConsumer”是什么意思? ps:这些都是你现学的么?从哪儿学的哇怎么学这么快懂这么多…[/quote] 写错了,应该是”surfaceTexture.java里面的成员mSurfaceTexture,他是int类型,实际是一个指向native层的GLConsumer对象的指针。“ 这些在android代码里面都有的,不要光看api,往下看看实现。
鱼儿_飞吧 2014-08-26
  • 打赏
  • 举报
回复
引用 56 楼 YKDSea 的回复:
引用 54 楼 yu8fei 的回复:
[quote=引用 53 楼 YKDSea 的回复:] 不知道你是怎么理解的,onFrameAvailable是回调函数,有新数据来的时候,才会被调用,不是看调用的参数。
是不知道怎么用。播放视频的时候数据流是有更新的,它就会一直被调用的,如果要进行数据处理,应该就是在这进行。 视频正播放的时候无画面输出,只有声音。 如果我要取出SurfaceTexture中的数据应该怎么取呢?
到jni层去操作就好做了,surfaceTexture.java里面的mSurfaceTexture分别对应了GLConsumer。 新的frame来的时候,先调用SurfaceTexture.updateTexImage()更新一下buffer,然后GLConsumer.getCurrentBuffer()可以拿到GraphicBuffer了,GraphicBuffer.lock()又可以直接拿到指针了。要注意color format。[/quote]不理解你这句话“surfaceTexture.java里面的mSurfaceTexture分别对应了GLConsumer”是什么意思? ps:这些都是你现学的么?从哪儿学的哇怎么学这么快懂这么多…
Aisy_D 2014-08-26
  • 打赏
  • 举报
回复
呵呵呵..... 一般android的显示一般有两层(或者两层以上), fb0, 和 fb1, fb1 在 fb0 的下面, fb1 显示软件的界面, fb0 平时一般是透明的, 在播放视频 的时候, 如果视频使用硬件解码, 解码后的 YUV 图像帧 直接 memcpy 到 fb0 的 framebuffer中, 这时候你就可以看到视频了, 中间不经过任何JAVA代码, 如果不是全屏, 那么fb0的只有视频区域的 alpha值 为 255, 其它区域为0, 使得后面的界面可以透上来... 你要抓 解码后的数据, 从GPU的驱动下手, HOOK一个接口出来可能有希望......
鱼儿_飞吧 2014-08-26
  • 打赏
  • 举报
回复
引用 64 楼 YKDSea 的回复:
mSurfaceTexture是在jni里面赋值的,java层的确看不到什么东西。从Surface入手,我觉得是不好做的,surface是处于一个生产者的角色,SurfaceTexture才是消费者,你现在是要使用player生产出来的buffer,从SurfaceTexture这边入手更合适。
绕来绕去的真心把SurfaceTexture和TextureView弄混了,一般都是继承TextureView再设置一个监听器TextureView.SurfaceTextureListener或者SurfaceTexture.OnFrameAvailableListener,
sky-Z 2014-08-26
  • 打赏
  • 举报
回复
引用 63 楼 yu8fei 的回复:
[quote=引用 62 楼 YKDSea 的回复:] VideoSurfaceView这个是你自己写的吧? 我的意思是要对SurfaceTexture扩展一下,前面说的成员都是class SufaceTexture中的,你要拿的buffer就在class SurfaceTexture中。
也不一定必须对SurfaceTexture扩展,Surface surface = new Surface(mSurfaceTexture);mMediaPlayer.setSurface(surface);这样播放的视频就在SurfaceTexture上了。 在SurfaceTexture.java中,定义的mSurfaceTexture并没有使用只是有那么一行注释,没有任何操作…扩展了SurfaceTexture也是没法从它入手的[/quote] mSurfaceTexture是在jni里面赋值的,java层的确看不到什么东西。从Surface入手,我觉得是不好做的,surface是处于一个生产者的角色,SurfaceTexture才是消费者,你现在是要使用player生产出来的buffer,从SurfaceTexture这边入手更合适。
鱼儿_飞吧 2014-08-26
  • 打赏
  • 举报
回复
引用 62 楼 YKDSea 的回复:
VideoSurfaceView这个是你自己写的吧? 我的意思是要对SurfaceTexture扩展一下,前面说的成员都是class SufaceTexture中的,你要拿的buffer就在class SurfaceTexture中。
也不一定必须对SurfaceTexture扩展,Surface surface = new Surface(mSurfaceTexture);mMediaPlayer.setSurface(surface);这样播放的视频就在SurfaceTexture上了。 在SurfaceTexture.java中,定义的mSurfaceTexture并没有使用只是有那么一行注释,没有任何操作…扩展了SurfaceTexture也是没法从它入手的
sky-Z 2014-08-26
  • 打赏
  • 举报
回复
VideoSurfaceView这个是你自己写的吧? 我的意思是要对SurfaceTexture扩展一下,前面说的成员都是class SufaceTexture中的,你要拿的buffer就在class SurfaceTexture中。
鱼儿_飞吧 2014-08-26
  • 打赏
  • 举报
回复
引用 60 楼 YKDSea 的回复:
引用 53 楼 YKDSea 的回复:
写错了,应该是”surfaceTexture.java里面的成员mSurfaceTexture,他是int类型,实际是一个指向native层的GLConsumer对象的指针。“这些在android代码里面都有的,不要光看api,往下看看实现。
mTextureID是int类型的,mSurfaceTexture是SurfaceTexture类型的
你看的哪个文件?我说的是class SurfaceTexture里面。[/quote]
class VideoSurfaceView extends GLSurfaceView {

    private VideoRender mRenderer;
    private MediaPlayer mMediaPlayer = null;

    public VideoSurfaceView(Context context, MediaPlayer mp) {
        super(context);

        setEGLContextClientVersion(2);
        mMediaPlayer = mp;
        mRenderer = new VideoRender(context);
        setRenderer(mRenderer);
        mRenderer.setMediaPlayer(mMediaPlayer);
    }
    
    @Override
    public void onResume() {
        queueEvent(new Runnable(){
                public void run() {
                    mRenderer.setMediaPlayer(mMediaPlayer);
                }});

        super.onResume();
    }

    private static class VideoRender
        implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
        ......
        private final float[] mTriangleVerticesData = {
            // X, Y, Z, U, V
            -1.0f, -1.0f, 0, 0.f, 0.f,
            1.0f, -1.0f, 0, 1.f, 0.f,
            -1.0f,  1.0f, 0, 0.f, 1.f,
            1.0f,  1.0f, 0, 1.f, 1.f,
        };

        private FloatBuffer mTriangleVertices;

        ......

        private float[] mMVPMatrix = new float[16];
        private float[] mSTMatrix = new float[16];

        private int mProgram;
        private int mTextureID;
        private int muMVPMatrixHandle;
        private int muSTMatrixHandle;
        private int maPositionHandle;
        private int maTextureHandle;

        private SurfaceTexture mSurfaceTexture;
        
        private boolean updateSurface = false;

        private MediaPlayer mPlayer;

        public VideoRender(Context context) {
            mTriangleVertices = ByteBuffer.allocateDirect(
                mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
            mTriangleVertices.put(mTriangleVerticesData).position(0);

            Matrix.setIdentityM(mSTMatrix, 0);
        }

        private void setMediaPlayer(MediaPlayer player) {
            mPlayer = player;
        }
        
        @Override
        public void onDrawFrame(GL10 glUnused) {
            synchronized(this) {
                if (updateSurface) {
                    mSurfaceTexture.updateTexImage();
                    mSurfaceTexture.getTransformMatrix(mSTMatrix);
                    updateSurface = false;
                }
            }

            ......

        }

        @Override
        public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        	
        }
        
        @Override
        public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
            ......

            int[] textures = new int[1];
            GLES20.glGenTextures(1, textures, 0);

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

            /*
             * Create the SurfaceTexture that will feed this textureID,
             * and pass it to the MediaPlayer
             */
            mSurfaceTexture = new SurfaceTexture(mTextureID);
            mSurfaceTexture.setOnFrameAvailableListener(this);

            Surface surface = new Surface(mSurfaceTexture);
            mPlayer.setSurface(surface);
            mPlayer.setScreenOnWhilePlaying(true);
            surface.release();

            try {
                mPlayer.prepare();
            } catch (IOException t) {
                Log.e(TAG, "media player prepare failed" + t);
            }

            synchronized(this) {
                updateSurface = false;
            }

            mPlayer.start();
            Log.i(TAG, "media player start");
        }
        
        synchronized public void onFrameAvailable(SurfaceTexture surface) {
            updateSurface = true;
        }

        private int loadShader(int shaderType, String source) {
            ......
            return shader;
        }

        private int createProgram(String vertexSource, String fragmentSource) {
            ......
            return program;
        }

        ......

    }  // End of class VideoRender.

}  // End of class VideoSurfaceView.
sky-Z 2014-08-25
  • 打赏
  • 举报
回复
引用 50 楼 yu8fei 的回复:
[quote=引用 47 楼 YKDSea 的回复:] [quote=引用 45 楼 yu8fei 的回复:] [quote=引用 44 楼 YKDSea 的回复:] [quote=引用 42 楼 yu8fei 的回复:] 错了错了,弄混乱了有点, 上面那个不是“读取camera图像流的例子”,是另外的一个 SurfaceTexture测试video用的, createProgram对应的俩个参数就是上面的两个字符串,求大神帮忙解释说明下,应该从哪里着手
camera里面有个api,setPreviewTexture来接收surfacetexture,但是mediaplayer没有这样的api的。[/quote]能使用SurfaceTexture代替SurfaceView来显示,播放电影应该就可以了吧,能做到吗这样?SurfaceTexture不会用也没有api,google打不开!![/quote] 下午看了下Surface的api,有个途径可以试下,写一个类似下面的class

public class LocalHolder  implements  SurfaceHolder{
	SurfaceTexture m_st;
	Surface m_surface;
	LocalHolder(SurfaceTexture st){
		m_st = st;
		m_surface = new Suface(m_st);
	}
	@Override
        public Surface getSurface() {
            return m_surface;
        }

	....//其他接口还需要补全
}
这样,你建立一个SurfaceTexture初始化后传给用这个texture构造一个LocalHolder出来, 然后Mediaplayer.setDisplay就传入LocalHolder对象。[/quote]这个API我知道,问题是播放不出来东西[/quote]、 surfacetexture界面上肯定是看不到东西的,先setOnFrameAvailableListener()设置个listener看看有没有数据上来,要想看到,还要把texture再画出去。
鱼儿_飞吧 2014-08-25
  • 打赏
  • 举报
回复
引用 47 楼 YKDSea 的回复:
[quote=引用 45 楼 yu8fei 的回复:] [quote=引用 44 楼 YKDSea 的回复:] [quote=引用 42 楼 yu8fei 的回复:] 错了错了,弄混乱了有点, 上面那个不是“读取camera图像流的例子”,是另外的一个 SurfaceTexture测试video用的, createProgram对应的俩个参数就是上面的两个字符串,求大神帮忙解释说明下,应该从哪里着手
camera里面有个api,setPreviewTexture来接收surfacetexture,但是mediaplayer没有这样的api的。[/quote]能使用SurfaceTexture代替SurfaceView来显示,播放电影应该就可以了吧,能做到吗这样?SurfaceTexture不会用也没有api,google打不开!![/quote] 下午看了下Surface的api,有个途径可以试下,写一个类似下面的class

public class LocalHolder  implements  SurfaceHolder{
	SurfaceTexture m_st;
	Surface m_surface;
	LocalHolder(SurfaceTexture st){
		m_st = st;
		m_surface = new Suface(m_st);
	}
	@Override
        public Surface getSurface() {
            return m_surface;
        }

	....//其他接口还需要补全
}
这样,你建立一个SurfaceTexture初始化后传给用这个texture构造一个LocalHolder出来, 然后Mediaplayer.setDisplay就传入LocalHolder对象。[/quote]这个API我知道,问题是播放不出来东西
加载更多回复(53)

80,350

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧