Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I can't display image when IP Camera Mjpeg use /snapshot.cgi or /videostream.cgi (issues detailed) #255

Closed
henriquem opened this issue Aug 18, 2014 · 5 comments

Comments

@henriquem
Copy link

Hello!
Please Help me in this situation:

I'm always use ip camera avaliable of internet for test, For example:

IPCamMjpeg arvore=  new IPCamMjpeg("Test", "http://plazacam.studentaffairs.duke.edu/axis-cgi/mjpg/video.cgi",IpCamMode.PUSH);

this example works fine very well!

But when I bought an ip camera ( with support MJPEG)
The configuration has few differents.

For example, when i access by browser, pressing the key F5 ( refresh) the images is captured very good!
I use the Url works: http://10.0.0.103:81/snapshot.cgi?loginuse=admin&loginpas=

I saw more details of network using F12 from browser google Chrome, you can see it:

Remote Address:10.0.0.103:81
Request URL:http://10.0.0.103:81/snapshot.cgi?loginuse=admin&loginpas=
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Authorization:Digest username="admin", realm="GoAhead", nonce="a60e29fd582457785cb8e9beecc4276b", uri="/snapshot.cgi?loginuse=admin&loginpas=", algorithm=MD5, response="3cfc333b74e850bc119e8fa3f7fe7509", opaque="5ccc069c403ebaf9f0171e9517f40e41", qop=auth, nc=00000074, cnonce="0992c20ab4edeb82"
Cache-Control:max-age=0
Connection:keep-alive
Host:10.0.0.103:81
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36
Query String Parametersview sourceview URL encoded
loginuse:admin
loginpas:
Response Headersview source
Connection:close
Content-Length:28556
Content-Type:image/jpeg
Server:GoaHead

But when I will use in framework I faced this problem:

IPCamMjpeg arvore=  new IPCamMjpeg("MyCam", "http://10.0.0.103:81/snapshot.cgi",IpCamMode.PUSH); 
//IpCamMode.PULL not works 
//or "http://10.0.0.103:81/snapshot.cgi?loginuse=admin&loginpas=" // nor work also 

I tried with authentication also: new IpCamAuth("admin","")
and Url http://10.0.0.103:81/videostream.cgi // not works

all attempts is occured Exception:

Using /snapshot.cgi

com.github.sarxos.webcam.WebcamException: Cannot download image
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice$PushImageReader.requestStream(IpCamDevice.java:100)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice$PushImageReader.<init>(IpCamDevice.java:65)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice.getImagePushMode(IpCamDevice.java:338)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice.getImage(IpCamDevice.java:321)
    at com.github.sarxos.webcam.ds.cgt.WebcamReadImageTask.handle(WebcamReadImageTask.java:43)
    at com.github.sarxos.webcam.WebcamTask.process(WebcamTask.java:40)
    at com.github.sarxos.webcam.ds.cgt.WebcamReadImageTask.getImage(WebcamReadImageTask.java:26)
    at com.github.sarxos.webcam.Webcam.getImage(Webcam.java:630)
    at com.github.sarxos.webcam.WebcamMotionDetector.detect(WebcamMotionDetector.java:275)
    at com.github.sarxos.webcam.WebcamMotionDetector$Runner.run(WebcamMotionDetector.java:87)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

(com.github.sarxos.webcam.WebcamExceptionHandler:32) - Exception in thread motion-detector-3
 com.github.sarxos.webcam.WebcamException: Cannot download image
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice$PushImageReader.requestStream(IpCamDevice.java:100)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice$PushImageReader.<init>(IpCamDevice.java:65)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice.getImagePushMode(IpCamDevice.java:338)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice.getImage(IpCamDevice.java:321)
    at com.github.sarxos.webcam.ds.cgt.WebcamReadImageTask.handle(WebcamReadImageTask.java:43)
    at com.github.sarxos.webcam.WebcamTask.process(WebcamTask.java:40)
    at com.github.sarxos.webcam.ds.cgt.WebcamReadImageTask.getImage(WebcamReadImageTask.java:26)
    at com.github.sarxos.webcam.Webcam.getImage(Webcam.java:630)
    at com.github.sarxos.webcam.WebcamMotionDetector.detect(WebcamMotionDetector.java:275)
    at com.github.sarxos.webcam.WebcamMotionDetector$Runner.run(WebcamMotionDetector.java:87)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.http.NoHttpResponseException: The target server failed to respond
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:95)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:717)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:522)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at com.github.sarxos.webcam.ds.ipcam.IpCamDevice$PushImageReader.requestStream(IpCamDevice.java:85)

Do you know what I can do ?
Thanks!

@sarxos
Copy link
Owner

sarxos commented Aug 19, 2014

Hi @henriquem,

The easiest would be to enable wire log from http client (it downloads the image) to see what is happening under the hood of IP camera driver. Wire log will print whole both HTTP request and response, so you can see how it differs from the original request from Firefox.

To enable wire log:

<configuration scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <logger name="org.apache.http.wire" level="INFO" />
    <logger name="org.apache.http.headers" level="DEBUG" />
    <logger name="com.github.sarxos.webcam.ds.ipcam" level="debug" />
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
  • The last but not least, in your source code, at the very beginning of the main(String[] args) method, put this line:
WebcamLogConfigurator.configure("logback.xml");

After your application is executed you should see what requests are being send by IP camera driver and what is being received, e.g. in case of http://plazacam.studentaffairs.duke.edu/axis-cgi/mjpg/video.cgi this will be:

12:08:19.941 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection request: [route: {}->http://plazacam.studentaffairs.duke.edu][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
12:08:19.942 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection leased: [id: 1][route: {}->http://plazacam.studentaffairs.duke.edu][total kept alive: 0; route allocated: 2 of 2; total allocated: 2 of 20]
12:08:19.942 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.i.c.DefaultClientConnectionOperator - Connecting to plazacam.studentaffairs.duke.edu:80
12:08:20.014 [Lignano-reader] DEBUG o.a.h.i.conn.DefaultClientConnection - Connection 0.0.0.0:60985<->152.3.16.13:80 closed
12:08:20.014 [Lignano-reader] DEBUG o.a.h.i.c.PoolingClientConnectionManager - Connection released: [id: 0][route: {}->http://plazacam.studentaffairs.duke.edu][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.c.protocol.RequestAddCookies - CookieSpec selected: best-match
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.c.protocol.RequestAuthCache - Auth cache not set in the context
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.c.p.RequestTargetAuthentication - Target auth state: UNCHALLENGED
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.c.p.RequestProxyAuthentication - Proxy auth state: UNCHALLENGED
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG c.g.s.w.d.ipcam.impl.IpCamHttpClient - Attempt 1 to execute request
12:08:20.073 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.i.conn.DefaultClientConnection - Sending request: GET /axis-cgi/mjpg/video.cgi HTTP/1.1
12:08:20.074 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - >> GET /axis-cgi/mjpg/video.cgi HTTP/1.1
12:08:20.074 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - >> Host: plazacam.studentaffairs.duke.edu
12:08:20.074 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
12:08:20.074 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.2.3 (java 1.5)
12:08:20.283 [webcam-panel-scheduled-executor-1] DEBUG o.a.h.i.conn.DefaultClientConnection - Receiving response: HTTP/1.0 200 OK
12:08:20.283 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << HTTP/1.0 200 OK
12:08:20.284 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << Cache-Control: no-cache
12:08:20.284 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << Pragma: no-cache
12:08:20.284 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << Expires: Thu, 01 Dec 1994 16:00:00 GMT
12:08:20.284 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << Connection: close
12:08:20.284 [webcam-panel-scheduled-executor-1] DEBUG org.apache.http.headers - << Content-Type: multipart/x-mixed-replace; boundary=myboundary

If the camera needs authentication (and what kind), you will most probably see this in the headers received on the GET request.

Now your goal is to verify what is being send when you stream MJPEG using Firefox (don't use Chrome - support for MJPEG on GET from URL bar has been deprecated). Simply use MJPEG URL and put it in browser's URL bar. Before you hit the enter run the browser console to observe the web traffic (rightclick somewhere and choose Inspect element (Q)).

plaza

In the Network tab you can check all headers which are send by Firefox and cookies, if any. If you track down what header/cookie is missing in wire log when you compare with log from Firefox console, you will most likely find what is wrong. Maybe webcam needs some other kind of authentication (the build in auth method is Basic Auth).

Just FYI, if you have a possibility to expose your webcam on the internet I can access it, and verify this on my own.

@henriquem
Copy link
Author

Thanks Sarxos, for good explanation
I will expose the ip cam on the internet temporarily for you see.

@henriquem
Copy link
Author

Hi sarxos, It is solved !
What I did ?

  • I change mode from IpCamMode.PUSH to IpCamMode.PULL
    because the framework recommends to use it in this line:

if (ct.getValue().startsWith("image/")) {
throw new WebcamException("Cannot read images in PUSH mode, change mode to PULL");
}

In this way works fine !
Thanks so much!

@henriquem
Copy link
Author

Sarxos,
Do you can clear my doubt ?

if you want to test the camera ip public is :

My doubt:
In IpCamDevice at method requestStream
return the content of URL : entity.getContent(); (image jpg)

So, the content from videostream.cgi is an Header ( source code use: Header ct = entity.getContentType();)
"Content-Type: text/html; charset=utf-8"

So, by IpCamMjpeg not is possible display images from "/videostream.cgi"
lentidão
Another alternative is use of "/snapshot.cgi", but the problem is slowness (mode PULL) than videostream.cgi (very fast fps!)

Do you know some solution for improve the shapshot.cgi ?
or another way to supports also videostream.cgi (if is possible).

Thanks!

@sarxos
Copy link
Owner

sarxos commented Aug 29, 2014

Hi @henriquem,

I just came back from the vacation, so please forgive me for no response in this time frame.

To make this clear:

  • PULL = static JPEG (client pull image from the server)
  • PUSH = MJPEG (Motion JPEG, server push image to client)

What is the difference?

  • In case of JPEG (PULL) your application will perform HTTP request each time when new image is necessary (yup, this will be many requests). This mode is useful when you do not need image to be refreshed very often or when the image itself is not being renewed for a long time (e.g. new image is generated on server once per 30 seconds). In this mode response mime type is image/jpeg (in most cases, but in code I just check if it starts with image/ to match also PNG and other)
  • In case of MJPEG (PUSH), only one request is being sent, and every new image is send by the server in the response stream. The consecutive images are separated by boundary and the mime type of such response is multipart/x-mixed-replace;boundary=ipcamera (the boundary string here may differ).

I tested above URL (MJPEG i.e. videostream.cgi) and used this code:

public class MjpegPushExample {

    /**
     * Remember to add IP camera driver JAR to the application classpath!
     * Otherwise you will not be able to use IP camera driver features. Driver
     * has to be set at the very beginning, before any webcam-capture related
     * method is being invoked.
     */
    static {
        Webcam.setDriver(new IpCamDriver());
    }

    public static void main(String[] args) throws MalformedURLException {

        // use this logback.xml only if file exists
        WebcamLogConfigurator.configure("src/examples/resources/logback.xml");

        String name = "Test #255";
        String url = "http://ce3014.myfoscam.org:20054/videostream.cgi";
        IpCamMode mode = IpCamMode.PUSH;
        IpCamAuth auth = new IpCamAuth("user", "user");

        IpCamDeviceRegistry.register(name, url, mode, auth);

        WebcamPanel panel = new WebcamPanel(Webcam.getWebcams().get(0));
        panel.setFPSLimit(1);

        JFrame f = new JFrame("Test #255");
        f.add(panel);
        f.pack();
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

And I had no issues after it's run:

image

For the authenticated static JPEG image, i.e. snapshot.cgi I used this one:

public class MjpegPushExample {

    static {
        Webcam.setDriver(new IpCamDriver());
    }

    public static void main(String[] args) throws MalformedURLException {

        // use only if you have this logback.xml file
        WebcamLogConfigurator.configure("src/examples/resources/logback.xml");

        String name = "Test #255";
        String url = "http://ce3014.myfoscam.org:20054/snapshot.cgi";
        IpCamMode mode = IpCamMode.PULL;
        IpCamAuth auth = new IpCamAuth("user", "user");

        IpCamDeviceRegistry.register(name, url, mode, auth);

        WebcamPanel panel = new WebcamPanel(Webcam.getWebcams().get(0));
        panel.setFPSLimit(1);

        JFrame f = new JFrame("Test #255");
        f.add(panel);
        f.pack();
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Also working well, but FPS rate is damn smaller (obviously) because of the way of how PULL work (multiple requests vs one in push), so for higher FPS PUSH has to be used with videostream.cgi.

Therefore, in regards to your comment:

So, the content from videostream.cgi is an Header ( source code use: Header ct = entity.getContentType();) "Content-Type: text/html; charset=utf-8"
So, by IpCamMjpeg not is possible display images from "/videostream.cgi"

I cannot agree with this statement since I proved empirically that fetching images is possible in both cases (PULL and PUSH).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants