0

Following my (dumb) question and reading this

I managed to connect to my cam, get the flow from it and dump it into an mpeg file. Here is the code for more clarity.

test "request headers from cam" do
    options = [basic_auth: {"LOGIN","PASSWORD"}, ibrowse: [{:save_response_to_file, true}]]
    {:ok, %HTTPoison.AsyncResponse{id: id}} = HTTPoison.get "http://x.x.x.x/axis-cgi/mjpg/video.cgi?duration=2&resolution=320x240",[], [stream_to: self, recv_timeout: :infinity, hackney: options
                                                                                                                                              ]
    {:ok, file} = File.open("/tmp/test.mpeg", [:write])
    retour = stream_to_file(id,file)
    send self,{:retour, retour}
    assert_receive {:retour ,:ok}, 10_000
  end

  defp stream_to_file(id, output) do
    receive do
     %HTTPoison.AsyncStatus{ id: ^id, code: code} ->
        IO.puts " AsyncStatus"
        stream_to_file(id,output)
      %HTTPoison.AsyncHeaders{ id: ^id} ->
        stream_to_file(id,output)
      %HTTPoison.AsyncEnd{ id: ^id} ->
        IO.puts " AsyncEnd received"
        :ok
      %HTTPoison.AsyncChunk{id: ^id, chunk: chunk} ->
        IO.binwrite(output, chunk)
        stream_to_file(id, output)
    end
  end

Test is running fine, a file is generated as expected but when i try to read it (using a couple of player), i can surreptitiously see one image from the cam and it stops rightafter.

Size (depending on parameters) can be important and when editing the file, i can clearly guess these are successive Jpeg files.

Here is the beginning of the file.

--myboundary Content-Type: image/jpeg Content-Length: 9609

ˇÿˇ‡JFIFˇ˛ W»XW»Xˇ˛ ß2¨ÃéTY"ˇ€C

It tried to play with several parameters without success, it looks like the file is not recognized as a mpeg file.

Any thoughts ? Regards, Pierre

Community
  • 1
  • 1
Tanc
  • 667
  • 3
  • 6
  • 25
  • What guarantees the original order of the chunks (bytes) as they are written to file with `stream_to_file`? – stephen_m Sep 01 '16 at 17:27
  • Tks for helping. Nothing i'm afraid. Only thing i can check with iHex is that all jpeg files inside are clearly separated by --myboundary I did copy a random block between to --myboundary separators, put it within a file and i had a correct image. – Tanc Sep 01 '16 at 18:45
  • MediaInfo doesn't seems to be able to extract any info from it. Did i forget to write header or something ? – Tanc Sep 01 '16 at 19:03

1 Answers1

0

In fact, Elixir/HTTPoison or HTTPotion wasn't responsible.

From Wikipedia

In multimedia, Motion JPEG (M-JPEG or MJPEG) is a video compression format in which each video frame or interlaced field of a digital video sequence is compressed separately as a JPEG image. Originally developed for multimedia PC applications, M-JPEG is now used by video-capture devices such as digital cameras, IP cameras, and webcams; and by non-linear video editing systems. It is natively supported by the QuickTime Player, the PlayStation console, and web browsers such as Safari, Google Chrome, Mozilla Firefox and Microsoft Edge.

I tried to manually extract Jpeg file from original file itself, and after a successfully attempt, quickest way i've found, was to use python (Can be slightly different if you are not in 2.7 eg : cv2.IMREAD_COLOR) and OpenCv.

import cv2
import urllib 
import numpy as np
import os

stream=open('./example.mjpg','rb')
sizemax = os.path.getsize("./example.mjpg")
bytes=''
allbytes = 0
nimage = 0
while nimage * 1024 < sizemax:
     nimage= nimage + 1
     bytes+=stream.read(1024)
     allbytes += allbytes + 1024
     a = bytes.find('\xff\xd8')
     b = bytes.find('\xff\xd9')
     if a!=-1 and b!=-1:
        jpg = bytes[a:b+2]
        bytes= bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
        cv2.imshow('i',i)
        if cv2.waitKey(1) ==27:
            exit(0) 

Regards,

Pierre

Tanc
  • 667
  • 3
  • 6
  • 25