Android MJPEG流

Android MJPEG流,android,video-streaming,mjpeg,Android,Video Streaming,Mjpeg,我已经实施了 并且还实现了异步和证书来运行上面提到的。现在我已经成功运行了jpeg视频流,但问题是它在运行流时一直闪烁。它不断地上下波动。我想可能是框架的问题。任何人都知道如何处理这件事。以下是我实现的完整代码: MjpegSample.java public class MjpegSample extends Activity { private static final boolean DEBUG=true; private static final String TAG = "MJPEG

我已经实施了

并且还实现了异步和证书来运行上面提到的。现在我已经成功运行了jpeg视频流,但问题是它在运行流时一直闪烁。它不断地上下波动。我想可能是框架的问题。任何人都知道如何处理这件事。以下是我实现的完整代码:

MjpegSample.java

public class MjpegSample extends Activity {

private static final boolean DEBUG=true;
private static final String TAG = "MJPEG";
private MjpegView mv;
private static final int MENU_QUIT = 1;
String URL;
MjpegInputStream inputStream;
/* 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
    URL = "https://orangefr-eu-oem-storage11.mios.com/storage/storage/store/81976/archive?Key=2147780009";
    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);        
    new DoRead().execute(URL);
}

public class DoRead extends AsyncTask<String, Void, MjpegInputStream> {
    protected MjpegInputStream doInBackground(String... url) {
        //TODO: if camera has authentication deal with it and don't just not work
        HttpResponse res = null;         
        DefaultHttpClient httpclient = new DefaultHttpClient(); 
        HttpParams httpParams = httpclient.getParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, 5*1000);
        HttpConnectionParams.setSoTimeout(httpParams, 5*1000);
        if(DEBUG) Log.d(TAG, "1. Sending http request");
        try {
            res = httpclient.execute(new HttpGet(URI.create(url[0])));
            if(DEBUG) Log.d(TAG, "2. Request finished, status = " + res.getStatusLine().getStatusCode());
            if(res.getStatusLine().getStatusCode()==401){
                //You must turn off camera User Access Control before this will work
                return null;
            }
            return new MjpegInputStream(res.getEntity().getContent());  
        } catch (ClientProtocolException e) {
            if(DEBUG){
                e.printStackTrace();
                Log.d(TAG, "Request failed-ClientProtocolException", e);
            }
            //Error connecting to camera
        } catch (IOException e) {
            if(DEBUG){
                e.printStackTrace();
                Log.d(TAG, "Request failed-IOException", e);
            }
            //Error connecting to camera
        }
        return null;
    }

    protected void onPostExecute(MjpegInputStream result) {
        mv.setSource(result);
        /*if(result!=null){
            result.setSkip(1);
            setTitle(R.string.app_name);
        }else{
            setTitle(R.string.title_disconnected);
        }*/
        mv.setDisplayMode(MjpegView.SIZE_FULLSCREEN);
        mv.showFps(false);
    }
}

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

MjpegInputStream.java

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));
}}
公共类MjpegInputStream扩展了DataInputStream{ 私有最终字节[]SOI_标记={(字节)0xFF,(字节)0xD8}; 私有最终字节[]EOF_标记={(字节)0xFF,(字节)0xD9}; 私有最终字符串内容\u LENGTH=“CONTENT LENGTH”; 专用最终静态int标头_MAX_LENGTH=100; 私有最终静态整数帧最大长度=40000+标题最大长度; private int mContentLength=-1; 公共静态输入流读取(字符串url){ HttpResponse; DefaultHttpClient httpclient=新的DefaultHttpClient(); 试一试{ res=httpclient.execute(新的HttpGet(URI.create(url)); 返回新的MjpegInputStream(res.getEntity().getContent()); }捕获(客户端协议例外e){ }捕获(IOE){} 返回null; } 公共MjpegInputStream(InputStream in){super(新的BufferedInputStream(in,FRAME_MAX_LENGTH));} private int getendofsequnce(DataInputStream in,字节[]序列)引发IOException{ int-seqIndex=0; 字节c; 对于(int i=0;i检查URL,我认为URL有问题。如果您想检查流媒体,您可以使用浏览器或VLC播放器进行检查,后者必须流媒体链接。我使用了相同的代码,从连接到机器人的摄像机上完美地流式播放。我实现了一个库,在Android上播放MJPEG视频流。GitHub上提供了所有源代码

将依赖项添加到应用程序中

compile 'com.github.niqdev:mjpeg-view:0.3.3'
下面是一个如何使用它的示例,将MjpegSurfaceView添加到布局中

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  // ADD THIS
  xmlns:stream="http://schemas.android.com/apk/res-auto"
  ...>

  <com.github.niqdev.mjpeg.MjpegSurfaceView
    android:id="@+id/VIEW_NAME"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    stream:type="stream_default OR stream_native" />

</RelativeLayout>

我们如何将lambda表达式转换为android支持的代码?要使用lamda表达式进行转换,您需要向gradle添加plugin
apply plugin:'me.tatarka.retrolambda'
。注意:jackOptions不适用于此。
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  // ADD THIS
  xmlns:stream="http://schemas.android.com/apk/res-auto"
  ...>

  <com.github.niqdev.mjpeg.MjpegSurfaceView
    android:id="@+id/VIEW_NAME"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    stream:type="stream_default OR stream_native" />

</RelativeLayout>
Mjpeg.newInstance()
 .credential("USERNAME", "PASSWORD")
 .open("IPCAM_URL.mjpg")
 .subscribe(inputStream -> {
    mjpegView.setSource(inputStream);
    mjpegView.setDisplayMode(DisplayMode.BEST_FIT);
    mjpegView.showFps(true);
 });