设为首页收藏本站

安徽论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 86203|回复: 0

音视频6.4——h264文件解码输出到Surface

[复制链接]

76

主题

0

回帖

240

积分

中级会员

Rank: 3Rank: 3

积分
240
发表于 2022-3-26 10:26:54 | 显示全部楼层 |阅读模式
网站内容均来自网络,本站只提供信息平台,如有侵权请联系删除,谢谢!
音视频开发路线:
Android 音视频开发入门指南_Jhuster的专栏的技术博客_51CTO博客_android 音视频开发入门
demo地址:
GitHub - wygsqsj/videoPath: 音视频学习路线demo
获取Surface

首先获取surface,我们MediaCodec解析出来的数据需要放到Surface中进行渲染,获取到surface之后开启解码线程
  1. protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_demo6);        surfaceview = findViewById(R.id.demo6Surface);        surfaceview.getHolder().addCallback(this); }......  //摄像头获取到的yuv数据回调    @Override    public void onPreviewFrame(byte[] data, Camera camera) {            }    @Override    public void surfaceCreated(SurfaceHolder holder) {       new H264DecodeThread(this, width, height, framerate, biterate, surface).start();    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }
复制代码
初始化MediaCodec

将我们初始化好的surface出入给MediaCodec,这样在我们的codec解码完数据后可以直接调用
releaseOutputBuffer(outputIndex, true); 第二个参数指定为true代表把当前的数据输出给surface,我们便可以看到视频了
  1. //初始化codecdecodeCodec = MediaCodec.createDecoderByType("video/avc");//初始化编码器final MediaFormat mediaformat = MediaFormat.createVideoFormat("video/avc", width, height);//设置帧率mediaformat.setInteger(MediaFormat.KEY_FRAME_RATE, biterate);decodeCodec.configure(mediaformat, surface, null, 0);decodeCodec.start();
复制代码
获取数据,进行解码

以分隔符0x00000001为基准,每次读取一个NALU单元的数据给MediaCodec解析,由于当前我们的数据较少,所以暂时一次全部读到byte数组中
  1. /** * 获取264所有的数据,一次性读取到内存中 */private byte[] getBytes() throws IOException {    int len;    int size = 1024;    byte[] bytes;    ByteArrayOutputStream bos = new ByteArrayOutputStream();    bytes = new byte[1024];    while ((len = is.read(bytes, 0, size)) != -1) {        bos.write(bytes, 0, len);    }    bytes = bos.toByteArray();    return bytes;}
复制代码
开启循环,找到当前NALU的数据,交给MediaCodec,需要注意的是,获取NALU分隔符时候,起始位置需要跳过几个字节,如果不跳过,每次都从分隔符前开始找,永远都是读到当前的分隔符就返回了,而我们需要找到下一个分隔符的位置,所以要跳过几个字节,不让读取当前第一个分隔符
  1. byte[] bytes = getBytes();//开始索引和当前得索引int startIndex = 0, nextIndex = 0;int totalSize = bytes.length;Log.i(LOG_TAG, "当前的数据大小" + totalSize);MediaCodec.BufferInfo decodeBufferInfo = new MediaCodec.BufferInfo();//用于描述解码得到的byte[]数据的相关信息while (true) {    Log.i(LOG_TAG, "当前的startIndex" + startIndex);    if (startIndex >= totalSize) {        break;    }    //sps为所有h264文件的起始值,也就是所有的h264起始值时0x01,所以加上一个随意的值,前面的sps就匹配不了了,否则nextIndex会永远读取不到数据    nextIndex = findByFrame(bytes, startIndex + 1);    Log.i(LOG_TAG, "当前的nextIndex" + nextIndex);    if (nextIndex == -1) {        break;    }    //获取codec输入数据载体    int inputIndex = decodeCodec.dequeueInputBuffer(10000);    if (inputIndex != -1) {        Log.i(LOG_TAG, "找到了input 小推车" + inputIndex);        ByteBuffer[] byteBuffers = decodeCodec.getInputBuffers();        ByteBuffer inputBuffer = decodeCodec.getInputBuffer(inputIndex);        inputBuffer.clear();        //把下一帧放入解码缓存        inputBuffer.put(bytes, startIndex, nextIndex - startIndex);        decodeCodec.queueInputBuffer(inputIndex, 0, nextIndex - startIndex, 0, 0);        //下一帧获取从当前末尾开始        startIndex = nextIndex;    } else {        Log.i(LOG_TAG, "没有可用的input 小推车");    }    //获取codec解码好的数据    int outputIndex = decodeCodec.dequeueOutputBuffer(decodeBufferInfo, 10000);//返回当前筐的标记    switch (outputIndex) {        case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:            Log.i(LOG_TAG, "输出的format已更改" + decodeCodec.getOutputFormat());            break;        case MediaCodec.INFO_TRY_AGAIN_LATER:            Log.i(LOG_TAG, "超时,没获取到");            break;        case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:            Log.i(LOG_TAG, "输出缓冲区已更改");            break;        default:            //config时已经把surface传给了codec,释放一下,第二个参数指定为true,codec自动会渲染到surface中            decodeCodec.releaseOutputBuffer(outputIndex, true);            break;    }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
免责声明
1. 本论坛所提供的信息均来自网络,本网站只提供平台服务,所有账号发表的言论与本网站无关。
2. 其他单位或个人在使用、转载或引用本文时,必须事先获得该帖子作者和本人的同意。
3. 本帖部分内容转载自其他媒体,但并不代表本人赞同其观点和对其真实性负责。
4. 如有侵权,请立即联系,本网站将及时删除相关内容。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表