我想在android上显示YUV视频 但是,我的项目只能显示视频的第一帧 我无法在当前状态下成功显示下一帧
以下是我的java代码:
public class SkiaView extends SurfaceView implements SurfaceHolder.Callback, Runnable
{
private SurfaceHolder holder=null;//******Version2******//
private static final String TAG = "skiademo";
private int mSampleId = 0;
// final Rect rect = new Rect(0, 0, 352, 288);
final int width=352,height=288;
int FrameNum=0;
static
{
System.loadLibrary("SkiaDemo");
}
public native void renderHello(Canvas canvas, int FrameNum,Rect rect);
public native void renderText(Canvas canvas);
class Pixel
{
byte Y,U,V;
};
private int[] YUV2RGB(byte [] YUV)
{
Byte R,G,B;
int y,x,i;
int [] argb = new int [width*height];
byte [] Y= new byte[width*height];
byte [] U= new byte[width*height];
byte [] V= new byte[width*height];
for(i=0;i<width*height;i++)
{
Y[i] =YUV[i];
if(i==0)
Log.d(TAG, "Y="+Y[i] +" YUV[i]=" +YUV[i]);
}
i=0;
byte container;
for(y=0;y<height/2;y++)
for(x=0;x<width/2;x++)
{
container =YUV[i+width*height];
U[y*2*width+x*2]=container;
U[y*2*width+x*2+1]=container;
U[(y*2+1)*width+x*2]=container;
U[(y*2+1)*width+x*2+1]=container;
i++;
}
i=0;
for(y=0;y<height/2;y++)
for(x=0;x<width/2;x++)
{
container =YUV[i+width*height+width*height/4];
V[y*2*width+x*2]=container;
V[y*2*width+x*2+1]=container;
V[(y*2+1)*width+x*2]=container;
V[(y*2+1)*width+x*2+1]=container;
}
for(i=0;i<width*height;i++)
{
R=(byte) (Y[i]+128+1.4075*(V[i]+128-128));
G=(byte) (Y[i]+128-0.3455*(U[i]+128-128)-0.7169*(V[i]+128-128));
B=(byte) (Y[i]+128+1.7790*(U[i]-128+128));
argb[i]=(0xff000000 + (B << 16) + (G << 8) + R);
if(i==0)
{
Log.d(TAG, "Y="+Y[i]+" U="+U[i]+ " V= "+V[i]);
Log.d(TAG, "R="+R+" G="+G+ "B= "+B+" argb="+argb[0]);
}
}
//Bitmap bmp=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
return argb;
}
private void readYUV(String src,byte[] YUV,int frame )
{
int i;
try {
FileInputStream inFile = new FileInputStream(src);
int filelength=inFile.available();
Log.d(TAG, "frame="+frame+" start="+width*height*1.5*frame+" Length="+width*height*1.5 + " Filelength="+filelength);
//inFile.read(YUV, (int)(width*height*1.5*(frame-1)),(int)(width*height*1.5));
for(i=0;i<width*height*1.5;i++)
YUV[i]=(byte) inFile.read();
Log.d(TAG, " YUV[i]=" +YUV[0]);
inFile.close();
} catch(FileNotFoundException fe) {
System.out.println("There is no such file!");
} catch(IOException ioe) {
System.out.println("IO exception!");
}
}
public SkiaView(Context context)//******Version2******//
{
super(context);
// TODO Auto-generated constructor stub
holder=getHolder();
holder.addCallback(this);
}
public void surfaceCreated(SurfaceHolder holder)//******Version2******//
{
// TODO Auto-generated method stub
new Thread(this).start();
}
private Bitmap Bytes2Bimap(byte[] b){
if(b.length!=0){
return BitmapFactory.decodeByteArray(b, 0, b.length);
}
else {
return null;
}
}
private void render(Canvas canvas,int i) {
canvas.drawColor(Color.BLACK);
byte [] YUV = new byte[(int) (width*height*1.5)];
int [] rgb = new int [width*height];
Bitmap bmp = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
readYUV("/mnt/sdcard/out_352x288_P420_final.yuv",YUV,i);
rgb=YUV2RGB(YUV);
bmp.setPixels(rgb, 0, width, 0, 0, width, height);
Log.d(TAG, "pixel="+bmp.getPixel(0, 0));
canvas.drawBitmap(bmp, 0, 0, null);
}
@Override
public void run() {
int i=0;
while(true)
{
Canvas canvas = holder.lockCanvas();
render(canvas,i);
i++;
if(i>=299)
i=0;
holder.unlockCanvasAndPost(canvas);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
我也尝试打印每个帧的第一个像素 所有内容都是一样的 它应该不是那样的
希望任何人都可以给我答案
答案 0 :(得分:1)
在readYUV()方法中,您似乎一遍又一遍地读取第一帧。每次打开到源文件的流时,它都从偏移量0开始。您需要使用FileInputStream.skip()方法来寻找每个帧的正确位置,或者将流指针保存在一个不变量的变量中。超出范围。你也应该在完成后关闭流。
答案 1 :(得分:1)
你没有在readYUV中寻求。它总是读取第一帧。
PS,如果图像很大,yuv2rgb可能成为瓶颈,尝试使用somr NEON优化版本。