2010-07-08 88 views
27

我需要從IP攝像頭獲取mjpeg流,任何人都知道正確的做法嗎?我用Google搜索了一下,我覺得這個例子Android和MJPEG

http://www.anddev.org/mjpeg_on_android_anyone-t1871.html

但我一直stucked當我試圖擺脫由主要活動稱爲另一個活動流。下面的代碼:

主要胡亞蓉

package com.test; 


public class IntentTest extends Activity { 
    /** Called when the activity is first created. */ 
    ListView myListView = null; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     myListView = (ListView)findViewById(R.id.listView); 
     final ArrayList<String> items = new ArrayList<String>(); 
     items.add("00408C944B9A"); 
     final ArrayAdapter<String> aa; 
     aa = new ArrayAdapter<String>(this, 
       android.R.layout.simple_list_item_1, 
       items); 

     myListView.setAdapter(aa); 
     myListView.setOnItemClickListener(listClicked); 

    } 


    private OnItemClickListener listClicked = new OnItemClickListener() { 
     public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) { 
      // TODO Auto-generated method stub 
      Intent i = new Intent(IntentTest.this, OtherActivity.class); 
      i.putExtra("MAC", myListView.getItemAtPosition(position).toString()); 
      startActivity(i);   
     } 
    }; 
} 

次活動

package com.test; 

import com.test.mjpeg.mjpegsample.MjpegView.*; 
import com.test.parser.JSONParse; 


public class OtherActivity extends Activity { 
    /** Called when the activity is first created. */ 
    private MjpegView mv; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Bundle extras = getIntent().getExtras(); 
     if (extras != null){ 
      String mac = (String)extras.get("MAC"); 
      Log.i("Other", "---->" + mac); 
      TextView tv = (TextView)findViewById(R.id.textView); 
      tv.setText(mac); 


      String URL = "myurl"; 

      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);  

     } 
    } 

    public void onPause() { 
     super.onPause(); 
     mv.stopPlayback(); 
    } 


} 

回答

38

我發現這個代碼在互聯網上,前一段時間,也許這將是對你有所幫助。

MjpegSample類

package de.mjpegsample; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.Window; 
import android.view.WindowManager; 
import de.mjpegsample.MjpegView.MjpegInputStream; 
import de.mjpegsample.MjpegView.MjpegView; 

public class MjpegSample extends Activity { 

    private MjpegView mv; 
    private static final int MENU_QUIT = 1; 

    /* Creates the menu items */ 
    public boolean onCreateOptionsMenu(Menu menu) {  
    menu.add(0, MENU_QUIT, 0, "Quit"); 
    return true; 
    } 

    /* Handles item selections */ 
    public boolean onOptionsItemSelected(MenuItem item) {  
     switch (item.getItemId()) { 
      case MENU_QUIT: 
       finish(); 
       return true;  
      }  
     return false; 
    } 

    public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 
     //sample public cam 
     String URL = "http://gamic.dnsalias.net:7001/img/video.mjpeg"; 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 
     mv = new MjpegView(this); 
     setContentView(mv);   
     mv.setSource(MjpegInputStream.read(URL)); 
     mv.setDisplayMode(MjpegView.SIZE_BEST_FIT); 
     mv.showFps(false); 
    } 

    public void onPause() { 
     super.onPause(); 
     mv.stopPlayback(); 
    } 
} 

MjpegView類

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類

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)); 
    } 
} 

如果您需要更多信息,請告訴我,我會盡我所能幫助您。

FYI:我沒有寫SimpleMjpegView,你可以找到更多的最新代碼here

+4

使用此代碼的任何未來的人我只想指出我的經驗。如果出現錯誤,您將會看到黑屏。我有證書問題,並沒有填補漁獲,沒有錯誤發佈到logcat。所以我只有一個黑屏。一旦我解決了所有的證書問題。 – 2012-04-23 14:01:22

+0

非常感謝您分享這些偉大的代碼 - 您拯救了我的一天! – herom 2012-05-08 14:18:08

+1

並且不要忘記清單中的互聯網許可 – Amt87 2012-09-06 09:28:53

0

我有同樣的問題,並嘗試使用自定義Mjpeg觀衆。當他們工作時,他們證明對我​​來說不穩定和笨拙。

我只是簡單地使用WebView。在Android Studio上,只需拖放WebView即可。我的WebView不覆蓋整個屏幕,而是覆蓋整個屏幕的一半。

然後,以適應視頻最好的,在你的onCreate:

如果使用科特林:

webView.settings.loadWithOverviewMode = true; 
webView.settings.useWideViewPort = true; 

如果使用Java:

webView.getSettings().setLoadWithOverviewMode(true); 
webView.getSettings().setUseWideViewPort(true); 

,然後就按一下按鈕:

開始:

webView.loadUrl("http://$id:8081/cam.mjpeg") // start 

要停止:

webView.stopLoading() 
webView.loadUrl("about:blank") 

希望這有助於。