DirectX: AudioVideoPlayback -> Problem mit Video-Klasse

Norbert Eder

Erfahrenes Mitglied
So, ausnahmsweise auch mal von mir eine Frage *g*.

Ich verwende die AudioVideoPlayback.dll aus dem DirectX 9 SDK. Das Abspielen von Videos funktioniert damit ansich recht gut, allerdings gibts doch (wie könnte es anders sein) ein Problem:

Das Video wird gestartet und abgespielt, danach wird ein anderes Video geladen und sollte auch abgespielt werden. Tut es auf dem Entwicklungsrechner auch, auf "sauberen" Systemen gibt's aber nur einen schwarzen Schirm.

Ich machte mich auf die Suche und fand heraus, dass es unter Umständen ein Problem mit der Audio-Instanz (welches die Video-Instanz ja besitzt) geben könnte. Dies ist nicht der Fall. Vielmehr ist mir aufgefallen, dass da ein ActiveMovie Prozess gestartet wird, der anscheinend weiterläuft und selbst beim null-setzen des Video-Objektes nicht gekillt wird. Dieser war zwar in der Taskliste der Testmaschinen nicht zu sehen, wollten aber beim Herunterfahren abgeschossen werden -> WTF?

Nun, wie arbeite ich damit? Ganz einfach:
Code:
Video v = new Video(videoFilename);
v.Ending += new ... // Event halt
v.Start();
Im Ending-Event wird das Object vom Typ Video auf null gesetzt. Im Internet ist es ständig mit Dispose() zu finden, was erstens nicht sauber ist und zweitens auch gar nicht funktioniert.

Hat hier jemand eine Idee woran das liegen könnte? Mir gehen schön langsam echt die Ideen aus.

PS: Ich verwende die letzte Version vom DirectX SDK VOR der aktuellen Version (diese teste ich gerade aus, scheint aber das gleiche Problem zu haben).

PPSS: Bitte kein Tipp in dem mir beschrieben wird, dass ich DirectShow verwenden soll. DirectShow ist mit dem DirectX October SDK deprecated.
 
Hallo Norbert!

Verwende doch lieber DirectShow ;) :p :D

Hehe. Nun zum Thema. :)
Hab mal ein Testprogramm fertig gemacht und es bei mir im Betrieb auf Win2000 & XP getestet.
Geht alles Prima. Ist glaube es ist auch die vorrangehende Version.
Also die 5.4.0.2904 des DXSDKs v9.02.2904.
Bin mir aber nicht sicher welche die vorrangehende Version ist.
Einen ActiveMovie Prozess konnte ich nicht feststellen. (Auch bei'm Herrunterfahren)
Code:
namespace Video_Test
{
	using System;
	using System.Drawing;
	using System.Windows.Forms;

	using Microsoft.DirectX.AudioVideoPlayback;


	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public class MainForm : Form
	{
		OpenFileDialog openFileDialog;
		Video DXvideo = null;
		Panel VideoPanel;

		#region Windows Forms Designer generated code

		/// <summary>
		/// This method is required for Windows Forms designer support.
		/// Do not change the method contents inside the source code editor. The Forms designer might
		/// not be able to load this method if it was changed manually.
		/// </summary>
		void InitializeComponent() {
			this.openFileDialog = new OpenFileDialog();
			// 
			// openFileDialog
			// 
			this.openFileDialog.Filter = "Video Dateien (*.avi)|*.avi|Alle Dateien (*.*)|*.*";
			this.openFileDialog.Title = "Video auswählen";
			// 
			// MainForm
			// 
			this.AutoScaleBaseSize = new Size( 5, 13 );
			this.ClientSize = new Size( 320, 240 );
			this.Name = "MainForm";
			this.Text = "Dx9 Video Player";
		}

		#endregion

		void CreatePanel() {
			if ( VideoPanel != null )
				this.Controls.Remove( this.VideoPanel );

			VideoPanel = null;
			VideoPanel = new Panel();
			this.VideoPanel.Dock = DockStyle.Fill;
			this.VideoPanel.Location = new Point( 0, 0 );
			this.VideoPanel.Name = "VideoPanel";
			this.VideoPanel.Size = new Size( 320, 240 );
			this.VideoPanel.TabIndex = 1;
			this.VideoPanel.MouseDown += new MouseEventHandler( this.panel1_MouseDown );
			this.Controls.Add( this.VideoPanel );
		}


		public MainForm() {
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			CreatePanel();
		}


		[STAThread]
		public static void Main( string[] args ) {
			Application.Run( new MainForm() );
		}


		void panel1_MouseDown( object sender, MouseEventArgs e ) {
			if ( e.Button == MouseButtons.Left ) {
				if ( DXvideo == null || DXvideo != null && !DXvideo.Playing )
					OpenVideo();
			}
			else if ( e.Button == MouseButtons.Right ) {
				if ( DXvideo != null && DXvideo.Playing )
					DXvideo.Stop();
				OpenVideo();
			}
		}


		void OpenVideo() {
			if ( openFileDialog.ShowDialog() == DialogResult.OK ) {
				try {
					if ( DXvideo == null )
						DXvideo = new Video( openFileDialog.FileName, false );
					else
						DXvideo.Open( openFileDialog.FileName );
					DXvideo.Owner = VideoPanel;
					DXvideo.Ending += new EventHandler( video_Ending );
					DXvideo.Play();

				}
				catch ( Exception ex ) {
					MessageBox.Show( ex.ToString(), "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error );
				}
			}
		}


		void video_Ending( object sender, EventArgs e ) {
/*			//Norberts Test
			DXvideo.Audio.Dispose(); // muss zuerst Disposed werden.
			DXvideo.Dispose(); // verursacht immer noch eine NullReferenceException

			DXvideo = null;
			CreatePanel();
*/
			OpenVideo();
		}
	}
}
LG, cosmo
 
Zuletzt bearbeitet:
Ich meinte die Summer-Editon. Keine Ahnung welche Versionsnummer die genau gehabt hat. Kannst mal folgendes probieren?

Video abspielen. Danach machst ein Dispose() bzw. wenn das nicht geht, einfach null setzen, das Panel verwerfen, danach Panel erstellen, Video-Objekt erstellen, Owner setzen und wieder starten. Geht das ohne Probleme?

Wie gesagt, auf meinem Rechner hier gehts auch problemlos, aber aber diversen anderen Rechnern eben nicht :(
 
Ja!
Ich bekomm aber das ActiveMovie Fenster wenn ich den video.Owner auf null setze bevor ich das Video-Objekt nulle.
Es wird aber mit dem beenden des Forms wieder geschlossen.
Hab [post=1177241]den Code oben[/post] sprechend deines Vorschlags geändert.

LG, cosmo
 
Ich muss es mal auf einem betroffenen Rechner testen.

Was hab ich gemacht?

1. Das Summer SDK durch das Oktober SDK ersetzt
2. DLL-Verweise entfernt und neu gesetzt
3. Im Control.Dispose sowohl Video.Audio.Dispose() als auch Video.Dispose() - jetzt scheint er alles zu entladen. Genau das Dispose ist im Summer SDK an _keiner_ Stelle gegangen.

Sieht aber derweil ganz gut aus. Eventuell also wirklich ein Summer SDK Bug.
 
Norbert Eder hat gesagt.:
Ich muss es mal auf einem betroffenen Rechner testen.

Was hab ich gemacht?

1. Das Summer SDK durch das Oktober SDK ersetzt
2. DLL-Verweise entfernt und neu gesetzt
3. Im Control.Dispose sowohl Video.Audio.Dispose() als auch Video.Dispose() - jetzt scheint er alles zu entladen. Genau das Dispose ist im Summer SDK an _keiner_ Stelle gegangen.

Sieht aber derweil ganz gut aus. Eventuell also wirklich ein Summer SDK Bug.
Mal ne Frage. Wenn Du sagst Du spielst die Videos immer wiederkehrend ab,
warum instenzierst dein VideoObjekt sammt Panel immer wieder neu?
Du hast mir nahe gelegt das sowas einen Overhead verursacht.
Meine erste Code version hatte lediglich den Pfad des abzuspielenden Videos geändert.
Klar wenn das wiedergeben sporadisch passiert kannst durch das nullen evtl Speicher Spaaren,
aber wann greift denn mal der GC? ;)
Händisch kurbelst ihn ja auch nicht an. Ich weiss von Dir dass das Unsinn ist.
Uns solange er nicht greift verdoppelst doch jeweils doch den Speicher,
oder etwa doch nicht? :confused:
Btw. Warum rufst jetzt Dispose auf, obwohl Du gesagt hast, das es unsauber ist
und obwohl es sowieso beim nullen passiert?

//Edit: Das SDK war immer noch vom 22.7.2005
 
Ok, um deine Fragen zu beantworten:

Ich muss es verwerfen und neu aufbauen, da es ein Template-System ist und hier wird die Ausgabe dynamisch erstellt. Es wird durch XML-Files angegeben, wie der Output auszusehen hat und dann entsprechend geladen und dargestellt. Den genauen Ablauf erspar ich dir jetzt, das sollte reichen um zu verstehen WARUM ich das auf diese Art und Weise mache.

Warum verwende ich Dispose?
Ganz einfach. Hinter dem Video-Objekt liegt unmanaged Code, welcher erst durch den Aufruf von Dispose entfernt wird -> siehe DirectX Doku.
 
Verstehe. Dann sollt ich mir in Zukunft die Dispose Doku zu allen Objekten mal genauer anschauen.
In bestimmten Fällen erreicht man also ein schnelleres Bereingen der genutzen Resourcen.

Wenn ich das DXVideo Objekt dispose bekomm ich aber eine NullReferenceException
entweder beim Start des Videos oder ein Weilchen danach.
Das war's was Du sicherlich meintst.
Ich zieh mir das neue SDK und probiers auch aus
und füge dann das Dispose und einen Comment in den Code oben mit hinzu.
 
So, nachdem ich das DX9 vom Oktober mit ca 14 KB/s runtergeladen hab, :eek: :suspekt: :mad:
directx_9c_oct05sdk_redist.exe
musste ich feststellen, dass ich beim handischen Disposen,
immer noch eine NullRefernceException, entweder beim Start des Videos oder kurz danach,
in der VideoWndProc bekomme.
Hab die DLL zum Test auch mal direkt aus dem Ordner referenziert.
Microsoft.DirectX.AudioVideoPlayback.dll hat gesagt.:
5.04.00.2904
C:\WINDOWS\Microsoft.NET\Managed DirectX\v9.02.2904\Microsoft.DirectX.AudioVideoPlayback.dll
Geht das jetzt etwa bei Dir? Wie kann das sein?
Hab ich jetzt evtl was falsch gemacht?

--> [post=1177241]zum Code[/post]
 
Zuletzt bearbeitet:
Tja, das disposen funktinoiert bei mir, wenn ich das im Control.Dipose mache. Dann hab ich kein Problem damit. An einer anderen Stelle funktionierts bei mir auch nicht.
 
Zurück