mpeg Auflösung ermitteln



  • hI!

    Hab dieses Programm geschrieben, um die Auflösung von einem mpg-Video zu ermitteln. Nun ist das bestimmt nicht das Gelbe vom Huhn, und da wollte ich mal fragen, ob das nicht einfacher geht, oder ob man an dem Programm noch etwas verbessern könnte, damit es schneller läuft oder sicherer ist.

    // Byte#      Data                Details
    // ===================================================================
    // 1-4        Sequence header     In Hex 000001B3
    //				code
    // 12 bits    Horizontal size     In pixels
    // 12 bits    Vertical size       In pixels
    // ...
    
    #include <windows.h>
    #include <stdio.h>
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    char Infotext[256];
    
    int WINAPI WinMain (HINSTANCE hI, HINSTANCE hPrevI, char* CmdLine, int ShowCmd)
    {	 
    	DWORD dwBuffer=0;
    	DWORD i=0;
    	long width=0;
    	long height=0;
    
    	fstream FileBin("irgendein.mpeg", ios::in|ios::out|ios::binary); 
    	if (FileBin.is_open()) 
    	{ 
    		char* pBuffer = new char[4]; 
    
    		// Sequence header code suchen
    		while(dwBuffer!=0x000001b3)
    		{
    			FileBin.seekg(i++, ios::beg); 
    			FileBin.read(pBuffer, 4); 
    			dwBuffer=(pBuffer[0]&255)<<24 | 
    				     (pBuffer[1]&255)<<16 | 
    					 (pBuffer[2]&255)<<8  | 
    					 (pBuffer[3]&255);
    		}
    
    		// gefunden, dann die nächsten 24 bit holen
    		i+=3;
    		FileBin.seekg(i, ios::beg); 
    		FileBin.read(pBuffer, 3); 
    
    		// jeweils 12 bit ausmaskieren
    		width=(pBuffer[0]&255)<<4 | (pBuffer[1]&240)>>4;
    		height=(pBuffer[1]&15)<<8 | (pBuffer[2]&255);
    
    		// und anzeigen
    		wsprintf(Infotext,"MPEG Resolution: %d x %d",width,height);
    		MessageBox(NULL,Infotext,"Test!",0);
    
    		// aufräumen
    		delete [] pBuffer;		
    	}	
    	return 0;
    }
    


  • Weiss jemand, in welchem Bereich der Header stehen muss? Ich frage deshalb, weil der Header Sequence Code bei kurzen Mpegs ziemlich am Anfang steht und bei anderen muss man erst 8 kb einlesen, um ihn zu finden. Gibts da sowas wie ein Maximum, z.b. dass der Header innerhalb der ersten 10 kb stehen muss?

    Und könnte mich mal einer ins Spieleforum verschieben? Hier interessiert sich wohl keiner dafür...danke!



  • Und könnte mich mal einer ins Spieleforum verschieben? Hier interessiert sich wohl keiner dafür...danke!

    nö! :p das passt nicht ins spiele forum.

    Eine grenze bis wann ein sequence header kommen muss gibt es nicht,(es können 100GB audio-subtitle-navigation-... packs im stream sein bevor eine neue videosequenz anfängt... ok, hätte wenig sinn 😃 ), sie muss nur am Anfang der video-sequence stehen.
    Was mir noch an deinem code auffällt ist das du 4 byte - blöcke aus der datei liest. Denke mal du verlässt dich hier drauf, dass das fstream schon für dich buffern wird. Würde ich nicht machen... Lies größe blöcke aus, denn wenn du pech hast greift dein prog jedes mal auf die Festlpatte zu wenn das read kommt. Wie groß du denn buffer wählst bleibt dir überlassen, aber 2048 Byte sollten es min. sein, für solche parser sachen lade ich die datei meisten in 1MB blöcken in die ram.



  • Wie stelle ich denn fest, dass ich beim buffern an das File-Ende gelangt bin, falls bis dahin kein sequence header gefunden wurde? kenn mich noch nicht so aus mit streams...



  • Indem du dir merkst wie viel im buffer ist 😉

    http://hypercubemx.free.fr/html/development_.html

    Das sind ein paar ziehmlich leicht verständliche klassen die genau das machen, er liest in blöcken aus der datei und zerlegt die daten dann in der Ram bitweise.
    Das Ding ist nicht grad das schnellste.. aber musst es ja nicht 1:1 übernehmen, denn davon lenr man nix 😃 :p
    Ein paar Ansätz um speed zu gewinnen:
    - MEPG-Stream ist in so genannte packs auftegteilt. Auf ner DVD sind die 2048 Byte lang auf ner SVCD 2324. Am anfang jedes packs steht eine sector-header die mit einem startcode beginnt (wie alles in MPEG 🤡 ). Dem starcode folgt die stream id. Diese stream-id gibt dir sofort aufschluss darüber was in diesem pack (den nächsten 2048 bzw. 2324 byte) an daten steht. Für dich intersannt sind nur packs mit der stream id "1110 xxxx", das ist ein video stream. Kurz zusammengfast:
    mpeg startcode + stream id -> "0000 0000 0000 0000 0000 0001" + "1110 xxxx"
    ====> haben die ersten 4 byte im sector nen wert zwischen 0x000001E0 und 0x000001EF schau rein ob da ne sequence header drin ist, sonst kannst gleich zum nächsten pack wandern und musst die daten da drinnen nicht parsen, weils sowieso keine video daten sind.
    - reagiere auf möglichst viele datenblöcke in deinem parser. Wie breits gesagt, in mepg beginnt alles mit nem startcode, diese 0x000001 kommt als häufig vor. Das byte danach sagt dir welche are von daten nun kommen.
    Wenn du einfach nur blind drauf lös suchst und alles ignorierst was nicht seq-header ist, musst du jedes byte unter die lupe nehmen.
    Wenn du allerdings auf den startcode einer GOP header reagierst, kannst gleich mal wieder 4 weiter wandern ohne zu suchen, da sind die GOP daten drinnen keine startcode, bei der picture header sinds schon ~8 Byte, die ganzen extensions.... alles verlorene zeit dort drinnen nach nem startcode zu suchen.
    Um an diese ganzen startcodes zu kommen besorg dir die ISO 13818-x und falls zu teuer ( :p ) such mal über google, gibt ne menge seite mit tuorials und infos darüber.
    - Sobald du mit buffern arbeitest begenest du früher oder später einem kleinen befehl namens memcpy. -> Nur in großen blöcken kopieren nich 2000 mal 1 Byte sondern 1 mal 2000 Byte kopieren. Verwende nicht das memcpy aus der CTR sondern
    nimm das hier:

    static __inline void fbcopy( void *d, void *s, int i)
    {
    	_asm {
    		mov ecx, i
    		mov esi, s
    		mov edi, d
    		rep movsb
    	}
    }
    

    (gibt auch noch schneller versionen, aber das ist dann schon MMX ect und musst checken ob die CPU das kann..... das ding hier läuft auf allen CPUs.

    dann mal viel spass 😃



  • Coole Info, danke! 👍 Werd mir das mal anschauen



  • oh.. kleiner fehler... die 0x000001E0 - 0x000001EF ist natürlich nicht die pack header (die ist 0x000001ba ) sondern die PES header.. musst das pack also bis zur PES header durchsuchen bist du weisst welcher stream es ist. Die kommt ziehmlich am Anfange meisten so um byte 0x0e - 0x30. Hast du sie und ist es keine video -> weiter zum nächsten pack 🤡

    http://mpucoder.kewlhair.com/derrow/

    saug dir mal VobEdit und offne damit ne vob-datei (MPEG2-Stream, auf DVDs im verzeichniss VIDEO_TS zu finden). Da siehst ziehmlich schnell wie so ne Datei aufgebaut ist. 🙂


Log in to reply