我从论坛中到一个android上的h264解码器,但解码速度很慢,图像也不大,只有352*288,播放出来完全是慢动作
请问大侠们,如何提高速度啊!!!
源码如下!
package h264.com;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;//////////////////////////////////////////////////////////////////
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class H264Android extends Activity {//有关窗口的各种事宜都在Activity中声明 VView vv;

    @Override
    public void onCreate(Bundle savedInstanceState) {//建立并显示一个窗口
        super.onCreate(savedInstanceState);
        vv = new VView(this);
        setContentView(vv);
    }
    
    // Menu item Ids
    public static final int PLAY_ID = Menu.FIRST;    
    public static final int EXIT_ID = Menu.FIRST + 1;     @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        
        menu.add(0, PLAY_ID, 0, R.string.play);   
        menu.add(0, EXIT_ID, 1, R.string.exit);        return true;
    }    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {        
        case PLAY_ID:
        {
          // 此处设定不同分辨率的码流文件
          
         String file = "/sdcard/352x288.h264"; //352x288.264"; //240x320.264"; 
         vv.PlayVideo(file);
        
            return true;
        }
        case EXIT_ID:
        {
         finish();
            return true;
        }
        }
        return super.onOptionsItemSelected(item);
    }
}//至此,对窗口的各种说明都完成class VView extends View  implements Runnable{
    
    Bitmap  mBitQQ  = null;   
    
    Paint   mPaint = null;   
       
    Bitmap  mSCBitmap = null;   
    
    Matrix matrix = new Matrix();  ////////////////////////////////////////////////////////////////////////////    
    int width = 352;  // 此处设定不同的分辨率
    int height = 288;    byte [] mPixel = new byte[width*height*2];//创建一个字符串mPixel,单位为byte,个数为width*height*2
    
    ByteBuffer buffer = ByteBuffer.wrap( mPixel );//将mPixel中的元素打包在Buffer中
Bitmap VideoBit = Bitmap.createBitmap(width, height, Config.RGB_565);  //以参数所要求的格式创建一个bitmap         
   
int mTrans=0x0F0F0F0F;

String PathFileName; 

    public native int InitDecoder(int width, int height);
    public native int UninitDecoder(); 
    public native int DecoderNal(byte[] in, int insize, byte[] out);
    
    static {
        System.loadLibrary("H264Android");
    }
    
    public VView(Context context) {//构造函数
        super(context);
        setFocusable(true);//使当前视图focused
        
        int i = mPixel.length;
    
        for(i=0; i<mPixel.length; i++)
        {
         mPixel[i]=(byte)0x00;//将mPixel中每个元素初始化为零
        }
    }
           
    public void PlayVideo(String file)//这是VView的核心!
    {
     PathFileName = file;        new Thread(this).start();//Thread构造器需要一个Runnable对象,使用start初始化,然后调用runnable的run方法!
    }
        
    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);//在画布上画图   
        
    //Bitmap VideoBit = Bitmap.createBitmap(width, height, Config.RGB_565);//.ARGB_8888); 在这面建Bitmap,视频播放更慢,貌似每三帧间还有暂停~           
    
        VideoBit.copyPixelsFromBuffer(buffer);//makeBuffer(data565, N));将buffer中的像素复制进VideoBit,但buffer中的像素并不变。
    
        matrix.postScale(1,1); /////////////////////////////////////////////////////////////////////////// 
        matrix.setRotate(90,120,130);  ////////////////////////////////////////////////////////////////////        canvas.drawBitmap(VideoBit, 0, 0, null); //在画布上绘制指定的bitmap
    }
    
    int MergeBuffer(byte[] NalBuf, int NalBufUsed, byte[] SockBuf, int SockBufUsed, int SockRemain)
    //将SockBuf中从第(SockBufUsed+1)元素到第(SockBufUsed+SockRemain)个元素add到NalBuf中,返回SockRemain
    {
     int  i=0;
     byte Temp;     for(i=0; i<SockRemain; i++)
     {
     Temp  =SockBuf[i+SockBufUsed];
     NalBuf[i+NalBufUsed]=Temp;//将剩余的Sock中SockRemain个像素全部都存NalBuf[]中,从NalBuf[NalBufUsed]接着存~     mTrans <<= 8;//左移八位
     mTrans  |= Temp;//和Temp各位相或     if(mTrans == 1) // 找到一个开始byte ??
     {
     i++;
     break;
     }
     }     return i;
    }
    
    public void run()   
    {           InputStream is = null;
     FileInputStream fileIS=null;
    
     int iTemp=0;
     int nalLen;
    
     boolean bFirst=true;
     boolean bFindPPS=true;
    
     int bytesRead=0;    
     int NalBufUsed=0;
     int SockBufUsed=0;
        
     byte [] NalBuf = new byte[40980]; // 40k个元素
     byte [] SockBuf = new byte[2048];//2k个元素
    
         
     try
     {    
      fileIS = new FileInputStream(PathFileName);//将文件PathFileName读入该流中
     }
     catch(IOException e) 
     {
     return ;
     } 
    
     InitDecoder(width, height); //根据宽高度初始化解码器
 
        while (!Thread.currentThread().isInterrupted())  //若当前进程没有被打断,便执行 
        {   
            try  
            {   
           bytesRead = fileIS.read(SockBuf, 0, 2048);//从流fileIS中读取2048个byte到SockBuf中,显然将其写满了,返回实际读取数
             //bytesRead = fileIS.read(SockBuf, 0, 2048);
             //  if(bytesRead<=0)
              // break;
           
            }
            catch (IOException e) {}
            
            if(bytesRead<=0)
             break;
            
            SockBufUsed =0;
            
     while(bytesRead-SockBufUsed>0)//若SockBuff中所存byte数,大于SockBufUsed数
     {
    
     nalLen = MergeBuffer(NalBuf, NalBufUsed, SockBuf, SockBufUsed, bytesRead-SockBufUsed);
    
     NalBufUsed+= nalLen;
     SockBufUsed+= nalLen;
    
     while(mTrans == 1)
     {
    
     mTrans = 0xFFFFFFFF;     if(bFirst==true) // the first start flag
     {
     bFirst = false;
     }
     else  // a complete NAL data, include 0x00000001 trail.
     {
     if(bFindPPS==true) // true
     {
     if( (NalBuf[4]&0x1F) == 7 )
     {
     bFindPPS = false;
     }
     else
     {
         NalBuf[0]=0;
          NalBuf[1]=0;
          NalBuf[2]=0;
          NalBuf[3]=1;
         
          NalBufUsed=4;
         
     break;
     }
     } 
     // decode nal
     iTemp=DecoderNal(NalBuf, NalBufUsed-4, mPixel);   

                 if(iTemp>0)
                 postInvalidate();  //使用postInvalidate可以直接在线程中更新界面    // postInvalidate();
     }     NalBuf[0]=0;
     NalBuf[1]=0;
     NalBuf[2]=0;
     NalBuf[3]=1;
    
     NalBufUsed=4;
     }
     } 
        } 
        try{        
        if(fileIS!=null)
         fileIS.close();
        if(is!=null)
         is.close();
        }
    catch (IOException e) {
     e.printStackTrace();
        }
        UninitDecoder();
    }  
}
问题可能对于高手不太难,我在线等一会啊~
谢了!

解决方案 »

  1.   

    硬件怎么样?
    用的不会是emulator吧
      

  2.   

    大哥,我这么低的分辨率,码流再高也不能卡吧,平台驱动的设置您能细讲一下么?硬件平台也有关系,我现在在emulator上跑的这么慢,是否是程序有缺陷,还是真机会比emulator快?大哥帮帮忙哇~
      

  3.   

    大哥,你在JAVA里做解码,然后构造BITMAP显示?不慢才怪呢!
    做解码,最好用native代码。
      

  4.   

    软件解码,对CPU处理要求比较高试试硬件上跑跑,如果有硬件加速可能的话
      

  5.   

    我也觉得是纯软的,大哥,如果硬件cpu足够快的话,我这程序里也没有设置延时函数,是不是有可能跑疯,视频超快跑过...
      

  6.   

    1.先在真机上试试
    2.按照9楼说的,用native c语言实现解码,在java中调用native函数
      

  7.   

    看代码也是调用native代码实现解码的啊。
    关注ing
      

  8.   

    楼主这个代码是调用的一个ffmpeg中的h264移植到android的native代码,播352*288的是会卡,可能是模拟器的缘故吧。
      

  9.   

    大哥,我的关键解码函数
     public native int InitDecoder(int width, int height);
        public native int UninitDecoder(); 
        public native int DecoderNal(byte[] in, int insize, byte[] out);
    都是用的natve,难道其他的buffer转换,构造bitmap等都应该用native?
      

  10.   

    JNI调用,虽然是本地的,但解码用的还是软件解码,接口函数背后是算法,没有使用硬件加速的缘故
      

  11.   

    软解码可以的,我师兄做出来了,我转做其他项目了,具体怎么做我也不清楚,但确定在真机上比在模拟器上跑的可快,在不加delay的情况下播放基本上是常速,所以还是慢,但比模拟器强多了,具体你研究下,可以搞出来的,要不android上岂不是开发不成播放器了,不可能的事情!呵呵~
      

  12.   

    大哥,你怎么知道这是在java里做解码。主要的解码函数DecodeNal也是通过C的Native代码实现的。没贴出来。
    模拟器上慢不代表真机上也慢,找个真机上试试不就知道了。
    另外。352x288在手机上已经不算小了。QCIF 176x144的才叫小。还有320x240的
      

  13.   

    很明显你这个调用的是ffmeg的api,我估计是模拟器的原因,你到真机上跑一下看效果如何
      

  14.   

    这个问题应该是机子性能的问题,我目前用的也是你这个库,用比较差的机子的话是会有两到三秒的延迟,用双核的机子的话差不多有不到一秒左右的延迟,但是现在问题是,这个库有问题,经常会崩掉,它里面的有一个是不能及时释放指针的好像,然后会造成一个 build fingerprinter的debug,程序崩溃,目前正在寻找硬解码方式来处理,不知道谁有没有好的办法。
      

  15.   

    现在也想利用这个代码做一些应用,速度我觉得还好,最大的问题是你们所说的bug,使用过程中不确定的崩溃报错,谁有解决方法,请帮忙提供一下,万分感谢。也可以私聊。企鹅 26560174