2013-09-09 5 views
10

Я хочу создать приложение с монодроидом, чтобы иметь живой видеопоток из IPCamera (с форматом MJpeg) на мой планшет. после копания в Интернете я обнаружил, что есть проект библиотеки Mjpeg, написанный на Java от here. он имеет два файла MjpegView.java и MjpegInputStream.Java, которые я положил их как здесь:Binding Library Mono для Android

MjpegView.java

package de.mjpegsample.MjpegView; 

import java.io.IOException; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.graphics.Rect; 
import android.graphics.Typeface; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MjpegView extends SurfaceView implements SurfaceHolder.Callback { 
    public final static int POSITION_UPPER_LEFT = 9; 
    public final static int POSITION_UPPER_RIGHT = 3; 
    public final static int POSITION_LOWER_LEFT = 12; 
    public final static int POSITION_LOWER_RIGHT = 6; 

    public final static int SIZE_STANDARD = 1; 
    public final static int SIZE_BEST_FIT = 4; 
    public final static int SIZE_FULLSCREEN = 8; 

    private MjpegViewThread thread; 
    private MjpegInputStream mIn = null;  
    private boolean showFps = false; 
    private boolean mRun = false; 
    private boolean surfaceDone = false;  
    private Paint overlayPaint; 
    private int overlayTextColor; 
    private int overlayBackgroundColor; 
    private int ovlPos; 
    private int dispWidth; 
    private int dispHeight; 
    private int displayMode; 

    public class MjpegViewThread extends Thread { 
     private SurfaceHolder mSurfaceHolder; 
     private int frameCounter = 0; 
     private long start; 
     private Bitmap ovl; 

     public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; } 

     private Rect destRect(int bmw, int bmh) { 
      int tempx; 
      int tempy; 
      if (displayMode == MjpegView.SIZE_STANDARD) { 
       tempx = (dispWidth/2) - (bmw/2); 
       tempy = (dispHeight/2) - (bmh/2); 
       return new Rect(tempx, tempy, bmw + tempx, bmh + tempy); 
      } 
      if (displayMode == MjpegView.SIZE_BEST_FIT) { 
       float bmasp = (float) bmw/(float) bmh; 
       bmw = dispWidth; 
       bmh = (int) (dispWidth/bmasp); 
       if (bmh > dispHeight) { 
        bmh = dispHeight; 
        bmw = (int) (dispHeight * bmasp); 
       } 
       tempx = (dispWidth/2) - (bmw/2); 
       tempy = (dispHeight/2) - (bmh/2); 
       return new Rect(tempx, tempy, bmw + tempx, bmh + tempy); 
      } 
      if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight); 
      return null; 
     } 

     public void setSurfaceSize(int width, int height) { 
      synchronized(mSurfaceHolder) { 
       dispWidth = width; 
       dispHeight = height; 
      } 
     } 

     private Bitmap makeFpsOverlay(Paint p, String text) { 
      Rect b = new Rect(); 
      p.getTextBounds(text, 0, text.length(), b); 
      int bwidth = b.width()+2; 
      int bheight = b.height()+2; 
      Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888); 
      Canvas c = new Canvas(bm); 
      p.setColor(overlayBackgroundColor); 
      c.drawRect(0, 0, bwidth, bheight, p); 
      p.setColor(overlayTextColor); 
      c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p); 
      return bm;   
     } 

     public void run() { 
      start = System.currentTimeMillis(); 
      PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER); 
      Bitmap bm; 
      int width; 
      int height; 
      Rect destRect; 
      Canvas c = null; 
      Paint p = new Paint(); 
      String fps = ""; 
      while (mRun) { 
       if(surfaceDone) { 
        try { 
         c = mSurfaceHolder.lockCanvas(); 
         synchronized (mSurfaceHolder) { 
          try { 
           bm = mIn.readMjpegFrame(); 
           destRect = destRect(bm.getWidth(),bm.getHeight()); 
           c.drawColor(Color.BLACK); 
           c.drawBitmap(bm, null, destRect, p); 
           if(showFps) { 
            p.setXfermode(mode); 
            if(ovl != null) { 
             height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight(); 
             width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth(); 
             c.drawBitmap(ovl, width, height, null); 
            } 
            p.setXfermode(null); 
            frameCounter++; 
            if((System.currentTimeMillis() - start) >= 1000) { 
             fps = String.valueOf(frameCounter)+"fps"; 
             frameCounter = 0; 
             start = System.currentTimeMillis(); 
             ovl = makeFpsOverlay(overlayPaint, fps); 
            } 
           } 
          } catch (IOException e) {} 
         } 
        } finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); } 
       } 
      } 
     } 
    } 

    private void init(Context context) { 
     SurfaceHolder holder = getHolder(); 
     holder.addCallback(this); 
     thread = new MjpegViewThread(holder, context); 
     setFocusable(true); 
     overlayPaint = new Paint(); 
     overlayPaint.setTextAlign(Paint.Align.LEFT); 
     overlayPaint.setTextSize(12); 
     overlayPaint.setTypeface(Typeface.DEFAULT); 
     overlayTextColor = Color.WHITE; 
     overlayBackgroundColor = Color.BLACK; 
     ovlPos = MjpegView.POSITION_LOWER_RIGHT; 
     displayMode = MjpegView.SIZE_STANDARD; 
     dispWidth = getWidth(); 
     dispHeight = getHeight(); 
    } 

    public void startPlayback() { 
     if(mIn != null) { 
      mRun = true; 
      thread.start();   
     } 
    } 

    public void stopPlayback() { 
     mRun = false; 
     boolean retry = true; 
     while(retry) { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (InterruptedException e) {} 
     } 
    } 

    public MjpegView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } 
    public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { thread.setSurfaceSize(w, h); } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     surfaceDone = false; 
     stopPlayback(); 
    } 

    public MjpegView(Context context) { super(context); init(context); }  
    public void surfaceCreated(SurfaceHolder holder) { surfaceDone = true; } 
    public void showFps(boolean b) { showFps = b; } 
    public void setSource(MjpegInputStream source) { mIn = source; startPlayback();} 
    public void setOverlayPaint(Paint p) { overlayPaint = p; } 
    public void setOverlayTextColor(int c) { overlayTextColor = c; } 
    public void setOverlayBackgroundColor(int c) { overlayBackgroundColor = c; } 
    public void setOverlayPosition(int p) { ovlPos = p; } 
    public void setDisplayMode(int s) { displayMode = s; } 
} 

MjpegInputStream.Java

package de.mjpegsample.MjpegView; 

import java.io.BufferedInputStream; 
import java.io.ByteArrayInputStream; 
import java.io.DataInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.URI; 
import java.util.Properties; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 

import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 

public class MjpegInputStream extends DataInputStream { 
    private final byte[] SOI_MARKER = { (byte) 0xFF, (byte) 0xD8 }; 
    private final byte[] EOF_MARKER = { (byte) 0xFF, (byte) 0xD9 }; 
    private final String CONTENT_LENGTH = "Content-Length"; 
    private final static int HEADER_MAX_LENGTH = 100; 
    private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH; 
    private int mContentLength = -1; 

    public static MjpegInputStream read(String url) { 
     HttpResponse res; 
     DefaultHttpClient httpclient = new DefaultHttpClient();  
     try { 
      res = httpclient.execute(new HttpGet(URI.create(url))); 
      return new MjpegInputStream(res.getEntity().getContent());    
     } catch (ClientProtocolException e) { 
     } catch (IOException e) {} 
     return null; 
    } 

    public MjpegInputStream(InputStream in) { super(new BufferedInputStream(in, FRAME_MAX_LENGTH)); } 

    private int getEndOfSeqeunce(DataInputStream in, byte[] sequence) throws IOException { 
     int seqIndex = 0; 
     byte c; 
     for(int i=0; i < FRAME_MAX_LENGTH; i++) { 
      c = (byte) in.readUnsignedByte(); 
      if(c == sequence[seqIndex]) { 
       seqIndex++; 
       if(seqIndex == sequence.length) return i + 1; 
      } else seqIndex = 0; 
     } 
     return -1; 
    } 

    private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException { 
     int end = getEndOfSeqeunce(in, sequence); 
     return (end < 0) ? (-1) : (end - sequence.length); 
    } 

    private int parseContentLength(byte[] headerBytes) throws IOException, NumberFormatException { 
     ByteArrayInputStream headerIn = new ByteArrayInputStream(headerBytes); 
     Properties props = new Properties(); 
     props.load(headerIn); 
     return Integer.parseInt(props.getProperty(CONTENT_LENGTH)); 
    } 

    public Bitmap readMjpegFrame() throws IOException { 
     mark(FRAME_MAX_LENGTH); 
     int headerLen = getStartOfSequence(this, SOI_MARKER); 
     reset(); 
     byte[] header = new byte[headerLen]; 
     readFully(header); 
     try { 
      mContentLength = parseContentLength(header); 
     } catch (NumberFormatException nfe) { 
      mContentLength = getEndOfSeqeunce(this, EOF_MARKER); 
     } 
     reset(); 
     byte[] frameData = new byte[mContentLength]; 
     skipBytes(headerLen); 
     readFully(frameData); 
     return BitmapFactory.decodeStream(new ByteArrayInputStream(frameData)); 
    } 
} 

так я преобразовал, что (на самом деле создать переменного тока # обертка) с Binding Library проект.

, но хотя я следовал пример кода учебник этого проекта следующим образом:

сам образец:

public class MjpegSample extends Activity { 
    private MjpegView mv; 

    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 

     //sample public cam 
     String URL = "http://webcam5.hrz.tu-darmstadt.de/axis-cgi/mjpg/video.cgi?resolution=320x240"; 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
          WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     mv = new MjpegView(this); 
     setContentView(mv);   

     mv.setSource(MjpegInputStream.read(URL)); 
     mv.setDisplayMode(MjpegView.SIZE_BEST_FIT); 
     mv.showFps(true); 
    } 

То, что я сделал в Monodroid:

namespace AndroidApplication8 
{ 
    [Activity(Label = "AndroidApplication8", MainLauncher = true, Icon = "@drawable/icon")] 
    public class Activity1 : Activity 
    { 
     int count = 1; 
     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 

      String URL = "rtsp://192.168.1.3/Mjpeg/video.cgi"; 
      var mv = new MjpegView(this); 
      SetContentView(mv); 
      **mv.SetSource(MjpegInputStream.Read(URL)); 
      mv.SetDisplayMode(MjpegView.SizeBestFit); 
      mv.StartPlayback(); 
     } 
    } 
} 

, но он дает мне ошибку в строке, обозначенной **, когда он хочет выполнить MjpegInputStream.Read()

и он переходит к классу, преобразованному из родных файлов Java, без дополнительной информации.

enter image description here

+0

Вы получаете дополнительную информацию об ошибках в VS или через LogCat? Вы пытались использовать FullScreen, а также в примере? – Philipp

+0

Какая ошибка? Если вы попытаетесь поймать исключение, вы получите что-нибудь? –

+0

Не могли бы вы накрутить URL-адрес «rtsp: //192.168.1.3/Mjpeg/video.cgi» в браузере Android и сообщить нам, работает ли потоковая передача? в противном случае вы должны проверить свой тип видео. –

ответ

1

Вы должны проверить видео type.For Например, если ваше кодирование видео сжимается там (прежде чем попасть на ваш андроид устройства), вы должны кодировать его, прежде чем положить его в ваши browser.This могут позволить вам написать код в java, например, чтобы сначала проверить входящий поток с камер (не использовать встроенный браузер android), а затем декодировать его вручную. Удачи!

 Смежные вопросы

  • Нет связанных вопросов^_^