Android和MJPEG [英] Android and MJPEG

查看:719
本文介绍了Android和MJPEG的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从IP摄像头获得的MJPEG流,任何人都知道正确的方式做到这一点?我用Google搜索了一下,我觉得这个例子

<一个href="http://www.anddev.org/mjpeg_on_android_anyone-t1871.html">http://www.anddev.org/mjpeg_on_android_anyone-t1871.html

但我一直stucked当我试图得到调用的主要活动的另一个活动流。在这里,code:

主要活性的研究

  com.test包;


公共类IntentTest延伸活动{
    / **第一次创建活动时调用。 * /
    ListView控件myListView = NULL;
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.main);

        myListView =(ListView控件)findViewById(R.id.listView);
        最后的ArrayList&LT;字符串&GT;项目=新的ArrayList&LT;字符串&GT;();
        items.add(00408C944B9A);
        最后ArrayAdapter&LT;字符串&GT; AA;
        AA =新的ArrayAdapter&LT;字符串&GT;(这一点,
                android.R.layout.simple_list_item_1,
                项);

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

    }


    私人OnItemClickListener listClicked =新OnItemClickListener(){
        公共无效onItemClick(适配器视图&LT;&GT;为arg0,查看ARG1,INT位置,长的id){
            // TODO自动生成方法存根
            意图I =新的意图(IntentTest.this,OtherActivity.class);
            i.putExtra(MACmyListView.getItemAtPosition(位置)的ToString());
            startActivity(ⅰ);
        }
    };
}
 

第二个活动

  com.test包;

进口com.test.mjpeg.mjpegsample.MjpegView *。
进口com.test.parser.JSONParse;


公共类OtherActivity延伸活动{
    / **第一次创建活动时调用。 * /
    私人MjpegView MV;
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        捆绑额外= getIntent()getExtras()。
        如果(临时演员!= NULL){
            字符串MAC =(字符串)extras.get(陆委会);
            Log.i(其他, - &gt;中+ MAC);
            TextView的电视=(TextView中)findViewById(R.id.textView);
            tv.setText(MAC);


            字符串的URL =myurl;

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

            MV =新MjpegView(本);
            的setContentView(MV);

            mv.setSource(MjpegInputStream.read(URL));
            mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
            mv.showFps(真正的);

        }
    }

    公共无效的onPause(){
        super.onPause();
        mv.stopPlayback();
    }


}
 

解决方案

我发现这个code在互联网前一段时间,也许这将是对你有所帮助。

MjpegSample类

 包de.mjpegsample;

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

公共类MjpegSample延伸活动{

    私人MjpegView MV;
    私有静态最终诠释MENU_QUIT = 1;

    / *创建菜单项* /
    公共布尔onCreateOptionsMenu(功能菜单){
    menu.add(0,MENU_QUIT,0,退出);
    返回true;
    }

    / *处理项目选择* /
    公共布尔onOptionsItemSelected(菜单项项){
        开关(item.getItemId()){
            案例MENU_QUIT:
                完();
                返回true;
            }
        返回false;
    }

    公共无效的onCreate(包冰柱){
        super.onCreate(冰柱);
        //样本公众凸轮
        字符串的URL =htt​​p://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 =新MjpegView(本);
        的setContentView(MV);
        mv.setSource(MjpegInputStream.read(URL));
        mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
        mv.showFps(假);
    }

    公共无效的onPause(){
        super.onPause();
        mv.stopPlayback();
    }
}
 

MjpegView类

 包de.mjpegsample.MjpegView;

进口java.io.IOException异常;

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

公共类MjpegView扩展了SurfaceView实现SurfaceHolder.Callback {
    公共最后静态INT POSITION_UPPER_LEFT = 9;
    公共最后静态INT POSITION_UPPER_RIGHT = 3;
    公共最后静态INT POSITION_LOWER_LEFT = 12;
    公共最后静态INT POSITION_LOWER_RIGHT = 6;

    公共最后静态INT SIZE_STANDARD = 1;
    公共最后静态INT SIZE_BEST_FIT = 4;
    公共最后静态INT SIZE_FULLSCREEN = 8;

    私人MjpegViewThread线;
    私人MjpegInputStream分钟= NULL;
    私人布尔showFps = FALSE;
    私人布尔mRun = FALSE;
    私人布尔surfaceDone = FALSE;
    私人油漆overlayPaint;
    私人诠释overlayTextColor;
    私人诠释overlayBackgroundColor;
    私人诠释ovlPos;
    私人诠释dispWidth;
    私人诠释dispHeight;
    私人诠释DISPLAYMODE;

    公共类MjpegViewThread继承Thread {
        私人SurfaceHolder mSurfaceHolder;
        私人诠释frameCounter = 0;
        私人长期的开始;
        私人位图OVL;

        公共MjpegViewThread(SurfaceHolder surfaceHolder,上下文语境){mSurfaceHolder = surfaceHolder; }

        私人矩形destRect(INT宝马,INT BMH){
            INT tempx;
            INT tempy;
            如果(DISPLAYMODE == MjpegView.SIZE_STANDARD){
                tempx =(dispWidth / 2) - (BMW / 2);
                tempy =(dispHeight / 2) - (BMH / 2);
                返回新的矩形(tempx,tempy,宝马+ tempx,BMH + tempy);
            }
            如果(DISPLAYMODE == MjpegView.SIZE_BEST_FIT){
                浮动bmasp =(浮点)宝马/(浮点)BMH;
                宝马= dispWidth;
                BMH =(INT)(dispWidth / bmasp);
                如果(BMH&GT; dispHeight){
                    BMH = dispHeight;
                    宝马=(INT)(dispHeight * bmasp);
                }
                tempx =(dispWidth / 2) - (BMW / 2);
                tempy =(dispHeight / 2) - (BMH / 2);
                返回新的矩形(tempx,tempy,宝马+ tempx,BMH + tempy);
            }
            如果(DISPLAYMODE == MjpegView.SIZE_FULLSCREEN)返回新的矩形(0,0,dispWidth,dispHeight);
            返回null;
        }

        公共无效setSurfaceSize(INT宽度,高度INT){
            同步(mSurfaceHolder){
                dispWidth =宽度;
                dispHeight =高度;
            }
        }

        私人位图makeFpsOverlay(涂料P,字符串文本){
            矩形B =新的矩形();
            p.getTextBounds(文字,0,text.length(),二);
            INT bwidth = b.width()+ 2;
            INT bheight = b.height()+ 2;
            位图BM = Bitmap.createBitmap(bwidth,bheight,Bitmap.Config.ARGB_8888);
            帆布C =新的Canvas(BM);
            p.setColor(overlayBackgroundColor);
            c.drawRect(0,0,bwidth,bheight,p)的;
            p.setColor(overlayTextColor);
            c.drawText(文字,-b.left + 1,(bheight / 2) - ((p.ascent()+ p.descent())/ 2)1,p)的;
            返回BM;
        }

        公共无效的run(){
            开始= System.currentTimeMillis的();
            PorterDuffXfermode模式=新PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
            位图BM;
            INT宽度;
            INT高度;
            矩形destRect;
            帆布C = NULL;
            涂料P =新的油漆();
            字符串FPS =;
            而(mRun){
                如果(surfaceDone){
                    尝试 {
                        C = mSurfaceHolder.lockCanvas();
                        同步(mSurfaceHolder){
                            尝试 {
                                BM = mIn.readMjpegFrame();
                                destRect = destRect(bm.getWidth(),bm.getHeight());
                                c.drawColor(Color.BLACK);
                                c.drawBitmap(BM,空,destRect,P);
                                如果(showFps){
                                    p.setXfermode(模式);
                                    如果(OVL!= NULL){
                                        高度=((ovlPos&安培; 1)== 1)? destRect.top:destRect.bottom-ovl.getHeight();
                                        宽度=((ovlPos和8)== 8)? destRect.left:destRect.right -ovl.getWidth();
                                        c.drawBitmap(OVL,宽度,高度,NULL);
                                    }
                                    p.setXfermode(空);
                                    frameCounter ++;
                                    如果((System.currentTimeMillis的() - 启动)&GT; = 1000){
                                        FPS =将String.valueOf(frameCounter)+FPS;
                                        frameCounter = 0;
                                        开始= System.currentTimeMillis的();
                                        OVL = makeFpsOverlay(overlayPaint,FPS);
                                    }
                                }
                            }赶上(IOException异常E){}
                        }
                    } {最后,如果(C!= NULL)mSurfaceHolder.unlockCanvasAndPost(C); }
                }
            }
        }
    }

    私人无效的init(上下文的背景下){
        SurfaceHolder支架= getHolder();
        holder.addCallback(本);
        线程=新MjpegViewThread(架,背景);
        setFocusable(真正的);
        overlayPaint =新的油漆();
        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();
    }

    公共无效startPlayback(){
        如果(MIN!= NULL){
            mRun = TRUE;
            thread.start();
        }
    }

    公共无效stopPlayback(){
        mRun = FALSE;
        布尔重试= TRUE;
        而(重试){
            尝试 {
                的Thread.join();
                重试= FALSE;
            }赶上(InterruptedException异常E){}
        }
    }

    公共MjpegView(上下文的背景下,ATTRS AttributeSet中){超(背景下,ATTRS);的init(上下文); }
    公共无效surfaceChanged(SurfaceHolder架,诠释楼INT W,INT高){thread.setSurfaceSize(W,H); }

    公共无效surfaceDestroyed(SurfaceHolder持有者){
        surfaceDone = FALSE;
        stopPlayback();
    }

    公共MjpegView(上下文的背景下){
        超(上下文);
        的init(上下文);
        }
    公共无效surfaceCreated(SurfaceHolder持有者){
        surfaceDone = TRUE;
        }
    公共无效showFps(布尔B){
        showFps = B;
        }
    公共无效的SetSource(MjpegInputStream源){
        MIN =来源;
        startPlayback();
        }
    公共无效setOverlayPaint(涂料P){
        overlayPaint = P;
        }
    公共无效setOverlayTextColor(INT C){
        overlayTextColor = C;
        }
    公共无效setOverlayBackgroundColor(INT C){
        overlayBackgroundColor = C;
        }
    公共无效setOverlayPosition(INT P){
        ovlPos = P;
        }
    公共无效setDisplayMode(int类型){
        DISPLAYMODE =秒;
        }
}
 

MjpegInputStream类

 包de.mjpegsample.MjpegView;

进口java.io.BufferedInputStream中;
进口java.io.ByteArrayInputStream中;
进口java.io.DataInputStream中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.net.URI中;
进口java.util.Properties;

进口org.apache.http.Htt presponse;
进口org.apache.http.client.ClientProtocolException;
进口org.apache.http.client.methods.HttpGet;
进口org.apache.http.impl.client.DefaultHttpClient;

进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;

公共类MjpegInputStream扩展的DataInputStream {
    私人最终的byte [] SOI_MARKER = {(字节)0xFF的,(字节)为0xD8};
    私人最终的byte [] EOF_MARKER = {(字节)0xFF的,(字节)0xD9};
    私人最终字符串CONTENT_LENGTH =内容长度;
    私人最终静态INT HEADER_MAX_LENGTH = 100;
    私人最终静态INT FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
    私人诠释mContentLength = -1;

    公共静态MjpegInputStream读(字符串URL){
        HTT presponse资源;
        DefaultHttpClient的HttpClient =新DefaultHttpClient();
        尝试 {
            RES = httpclient.execute(新HTTPGET(URI.create(URL)));
            返回新MjpegInputStream(res.getEntity()的getContent());
        }赶上(ClientProtocolException E){
        }赶上(IOException异常E){}
        返回null;
    }

    公共MjpegInputStream(InputStream中的){超(新的BufferedInputStream(中,FRAME_MAX_LENGTH)); }

    私人诠释getEndOfSeqeunce(在的DataInputStream,byte []的顺序)抛出IOException异常{
        INT seqIndex = 0;
        字节℃;
        的for(int i = 0; I&LT; FRAME_MAX_LENGTH;我++){
            C =(字节)in.readUnsignedByte();
            如果(C ==序列[seqIndex]){
                seqIndex ++;
                如果(seqIndex == sequence.length)返回I + 1;
            }否则seqIndex = 0;
        }
        返回-1;
    }

    私人诠释getStartOfSequence(在的DataInputStream,byte []的顺序)抛出IOException异常{
        INT端= getEndOfSeqeunce(中,序列);
        返回(完℃下)? (-1):(结束 -  sequence.length);
    }

    私人诠释parseContentLength(byte []的headerBytes)抛出IOException异常,NumberFormatException的{
        ByteArrayInputStream的headerIn =新ByteArrayInputStream的(headerBytes);
        属性道具=新特性();
        props.load(headerIn);
        返回的Integer.parseInt(props.getProperty(CONTENT_LENGTH));
    }

    公共位图readMjpegFrame()抛出IOException异常{
        标记(FRAME_MAX_LENGTH);
        INT headerLen = getStartOfSequence(这一点,SOI_MARKER);
        复位();
        byte []的头=新的字节[headerLen]
        的readFully(头);
        尝试 {
            mContentLength = parseContentLength(头);
        }赶上(NumberFormatException的NFE){
            mContentLength = getEndOfSeqeunce(这一点,EOF_MARKER);
        }
        复位();
        byte []的frameData =新的字节[mContentLength]
        的skipBytes(headerLen);
        的readFully(frameData);
        返回BitmapFactory.de codeStream(新ByteArrayInputStream的(frameData));
    }
}
 

如果您需要任何更多的信息,让我知道,我会帮以任何方式,我可以。

供参考:我没有写SimpleMjpegView,你可以找到更多的最新code

I need to get the mjpeg stream from an IP camera, anyone know the right way do it? I googled a bit and I find this example

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

but I've been stucked when I tried to get the stream from another activity called by the main activity. Here the code:

Main acitivity

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

Second activity

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


}

解决方案

I found this code over the internet some time ago, maybe it will be of some help to you.

MjpegSample Class

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 Class

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 Class

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

If you need any more info, let me know, I'll help in any way I can.

FYI: I did not write SimpleMjpegView, you can find more up to date code here

这篇关于Android和MJPEG的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆