# MJPEG Stream aufnehmen (Speichern und von VirtualDub weiterverarbeiten lassen).



## MWCS (16. Aug 2012)

Hallo,

Ich habe hier eine Webcam vorliegen und wollte mal den MJPEG-Stream anzapfen. Das habe ich auch soweit geschafft. Das hier ist mein Code:


```
package camsurv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.io.FileWriter;

public class MJPEGParser {

	public static void main(String[] args) {
		MJPEGParser mp = new MJPEGParser("http://192.168.12.19");
	}

	public MJPEGParser(String mjpeg_url)
	{
		int imageCount = 0;
		
		try {
			FileWriter fw = null;

            URL url = new URL(mjpeg_url);
            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
            String inputLine;
            int lineCount = 0;
            boolean lineCountStart = false;
            boolean saveImage = false;
            while ((inputLine = in.readLine()) != null) {
            	// Should be checking just for "--" probably
            	if (inputLine.lastIndexOf("--WebCamImage") > -1)
            	{
            		// Got an image boundary, stop last image
            		// Start counting lines to get past:
            		// Content-Type: image/jpeg
            		// Content-Length: 22517

            		saveImage = false;
            		lineCountStart = true;
            		System.out.println("Got a new boundary");
            		System.out.println(inputLine);
            		if(imageCount != 0)
            			fw.write(inputLine);
            		if(fw != null)
            			fw.close();
            		fw = new FileWriter("C:\\eclipse\\bild" + imageCount + ".jpg");
            	}
            	else if (lineCountStart)
            	{
            		lineCount++;
            		if (lineCount >= 2)
            		{
            			lineCount = 0;
            			lineCountStart = false;
            			imageCount++;
            			saveImage = true;
                		System.out.println("Starting a new image");

            		}
            	}
            	else if (saveImage)
            	{
            		System.out.println("Saving an image line");
            		fw.write(inputLine);
            	}
            	else {

            		System.out.println("What's this:");
            		System.out.println(inputLine);
            	}
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }		

	}

}
```

Das ganze funktioniert auch gut, ich bekomme damit Bilder wie sie sein sollen gespeichert, aber diese können nicht geöffnet werden.

IrfanView sag das die Quantisierungstabelle der Datei beschädigt sei. Ich weiß nicht woran das Liegt, ich habe mal so ein stück Stream angehängt, vllt. kann mir eine erklären was an der JPEG nicht stimmt. So wie ich das sehe ist alles da der SOI, JFIF, SOS und EOI Tag. Warum das Bild korrupt ist kann ich mir nicht erklären...


----------



## twseitex (20. Aug 2012)

Bilddatei JPG zu RGB-Werte bzw. Bild aus RGB-Werten erzeugen

Also, ich habe folgendes Prinzip benutzt:

1) Eine Bilddatei wird zu int-Feld aus RGB-Werten umgewandelt, per

 	BufferedImage X06=null;
 	int[][] X07=null;
 	BufferedInputStream X08=null;



   Der gepufferten Inputstream der Datei im aktuellen Pfad ist zu erzeugen

   Mit diesem Stream (X08) dann Buffered Image (X06) füllen


 	 try
		{X06=ImageIO.read(X08);}
	 	catch (MalformedURLException e1)
		 {
		  ....

		 }
		 catch (IOException e2)
		 {
		  ....
		 }

		// ----- BufferedInputStream schliessen
 		try
 		{X08.close();}
 		catch (IOException e3)
 		{
 		 // nichts
 	        }
	}

   Mit diesem buffered Image das int-Feld (X07) füllen

 	{
 	 X07=new int[X01][X02];
 	 for(int i=0;i<X01;i++)
 	 {for(int j=0;j<X02;j++)
 	  {X07_[j]=X06.getRGB(i,j);}
 	  		// nur Bildtyp BufferedImage.TYPE_INT_ARGB
 	  		//             RGB Standard-Colorspace also 32 Bit
 	 }
 	}

 	// int intRGBWert=....
 	// int intBlau  =(intRGBWert >> 0)  & 0xff;  // Bit 0-7
 	// int intGruen =(intRGBWert >> 8)  & 0xff;  // Bit 8-15
 	// int intGelb  =(intRGBWert >> 16) & 0xff;  // Bit 14-23
 	// int intAlpha =(intRGBWert >> 24) & 0xff;  // Bit 24-31

 	return X07;


2) RGB-Intfeld zu Buffered Image

  BufferedImage X04=null;

   X04=new BufferedImage(X01,X02,BufferedImage.TYPE_INT_ARGB);
   {
    for(int i=0;i<X01;i++)
 	  {for(int j=0;j<X02;j++)
     {X04.setRGB(i,j,X00[j]);}
    }
   }


Ergo Komponenten benutzen, die Image-Daten verwalten und nicht reine Dateidaten.
Und buffered arbeiten.

Klar, das int-Feld habe ich auch als Stringfeld erzeugen lassen, also Text,
den ich in den Javacode einbauen kann, so dass kleine JPD-Dateien nicht
erst geladen werden müssen, sondern von string nach int-konvertiert dann
zum java-verwalteten Bild. .... Für Bildfolgen von Webcams wohl nichts.
Aber als Ersatz für aninmiertes GIF aus Folge von kleinen Bilddaten geht das
schon mal (zu sehen in meinem Audio-Media-Player auf audio, flash and java)._


----------



## MWCS (20. Aug 2012)

Hab mein Code mal angepasst...


```
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

class MJPEGParserNeu{
	public static void main(String[] args){
		try {
			URL url = new URL("http://141.45.165.42/axis-cgi/mjpg/video.cgi");
			InputStreamReader isr = new InputStreamReader(url.openStream());
			BufferedReader br = new BufferedReader(isr);
                        FileOutputStream fos = null;
			byte[] arry = null;
			int count = 0;
			for(int i = 0; i < 1000; i++)
			{
				arry = new byte[0];
				fos = new FileOutputStream("C:\\eclipse\\bilder\\bild" + count + ".jpg");
				byte by = (byte) br.read();
				if(by == (byte) 0xff){
					by = (byte) br.read();
					if(by == (byte) 0xd8){
						System.out.println("Picture found, start capturing...");
						arry = addByte(arry, (byte) 0xff);
						arry = addByte(arry, (byte) 0xd8);
						while(true)
						{
							by = (byte) br.read();
							if(by == (byte) 0xff){
								by = (byte) br.read();
								if(by == (byte) 0xd9){
									arry = addByte(arry, (byte) 0xff);
									arry = addByte(arry, (byte) 0xd9);
									System.out.println("Picture ends, stopped capturing...");
									fos.write(arry);
									fos.close();
									count++;
									break;
								}
								else
								{
									arry = addByte(arry, (byte) 0xff);
									arry = addByte(arry, by);
								}
								}
							else{
								arry = addByte(arry, by);
							}
						}
					}
				}
			}
			br.close();
			isr.close();
			System.out.println("Picture writing successful!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	static byte[] addByte(byte[] arry, byte by){
		byte[] arry2 = new byte[arry.length+1];
		for(int i = 0; i < arry.length; i++){
			arry2[i] = arry[i];
		}
		arry2[arry.length] = by;
		return arry2;
	}
}
```

Jetzt bekomme ich wenigstens Bilder, die sind aber alle Crap. Eigentlich Datenmüll, aber woher kommt das?

Wer es Testen will: Die eingetragene URL zeigt auf eine Webcam in Berlin. Die Quelle ist hier zu finden: Webcam in Berlin, Germany


----------

