MediaCodec设置End-of-stream状态用于迅速推出内部数据(起名无能)

使用MediaCodec进行硬解码通常有两种模式:同步and异步。
异步是由硬解码器通过回调函数送取数据,由于我没有过这种方式,所以不清楚异步下是否会出现解码器存帧现象。
同步的话是由我选择什么时候送取数据,总体流程就是
1>送数据:

Public int InputData(byte[] data,int Len,int timeStamp)
{
	if(data == null || len <= 0)
	{
	   return -1;
	}
	int inputIndex = -1;
	try{
	   //获取解码器输入buffer的index
	   //此处形参是MediaCodec输入buffer的等待时间,这里为0
	   inputIndex = MediaCodec.dequeueInputBuffer(0);
	}
	catch(Exception e)
	{
	   e.printStackTrace();
	   return -1;
	}
	
	if(inputIndex <0)
	{
	   return -1;
	}
	
	//送入解码数据
        ByteBuffer inputBuffer = codec.getInputBuffer(inputIndex);
        inputBuffer.clear();
        inputBuffer.put(data,0,len);

	try{
	   MediaCodec.queueInnputBuffer(inputIndex,0,len,timeStamp,0);
	}
	 catch(Exception e)
 	{
    	   e.printStackTrace();
           return -1;
	}
	return 0;
}

2>取数据

public int OutputData()
{	
	int outputIndex = -1;
	BufferInfo bufferinfo = new BufferInfo();
	try{
	   outputIndex = MediaCodec.dequeueOutputBuffer(bufferinfo,0);
	}
	catch(Exception e)
	{
	   e.printStackTrace();
	   return -1;
	}
	
	if(outputIndex >= 0)
	{
	   //成功获取解码器输出index
	   bufferinfo.presentationTimeUs;//时间戳
	   bufferinfo.size;//大小
	}
	else
	{
           //若outputIndex为-1,则硬解码器暂时没有解码后数据 
	   retrun -1;
	}

	return 0}

3> 渲染

public int Render(int outputIndex, boolean isRender)
{
	if(outputIndex < 0)
	{
	   return -1;
	}
	
	try
	{
	   //此处outputIndex是由OutputData获取到的,isRender为true则MediaCodec会将解码后的纹理直接渲染到创建时绑定的Surface上
	   MediaCodec.releaseOutputBuffer(outputIndex,isRender);
	}
	catch(Exception e)
	{
	   e.printStackTrack();
	   return -1;
	}

	return 0;
}

以上3个步骤可以在同一个线程内进行,也可在不同线程内调用。
但无论是一个线程还是多个线程,都会出现MediaCodec内部存几帧的情况,这样实时流下会增加延时,而文件模式下硬解码器内部存的这几帧数据会无法推出渲染。

我尝试过专门开一个线程去取输出缓存区的index,但是发现某些设备上这几帧还是无法取出,后来看Android开发者手册发现,MediaCodec是有3种状态的,running、flush、end-of-stream,可以通过设置End-of-stream标志位来告诉MediaCodec无数据要解了,这种模式下是无法获取输入缓冲区的index的,但是还是可以继续获取输出缓冲区的index,经过尝试,将MediaCodec设置为end-of-stream模式可以迅速的取出解码器内部存的那几帧。

4>设置End-of-stream

public int SetEndofStream()
{
	int inputIndex = -1;	
	try{	
	      inputIndex = MediaCodec.dequeueInputBuffer(0);
 	}
 	catch(Exception e)
 	{
    	      e.printStackTrace();
    	      return -1;
 	}
	
	if(inputIndex < 0 )
	{
	      //需要重新获取
	      return -1;
	}

	try{
	      MediaCodec.queueInputBuffer(inputIndex,0,0,0,MediaCodec.BUFFER_FLAG_END_OF_STREAM);
	}
	catch(Exception e)
	{
	      e.printStackTrace();
	      return -1;
	}
	return 0;
}

SetEndofStream()还可以用于清空硬解码器,如果设置End-of-stream后还需要继续解码只需要调用MediaCodec.flush();把硬解码器设置为等待状态,然后再inputdata就可以继续解码了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值