The AsfWriter's File

 

Disabling The AsfWriter's File Writer

When the FilterGraph is activated, the AsfWriter does three things:-
  1. The AsfWriter creates an ASF stream, the properties of which are determined by the parameters in a Profile. The Profile is based on an XML file containing stream settings such as whether both audio and video are present, the bitrate(s) of each, the width and height of the video image and so on;

  2. The AsfWriter streams the resulting ASF stream onto the network using the AsfWriter's network properties such as the IP address, the Port number and so on. Some of these properties (such as the Port number) are configurable, some (such as the IP address) are obtained from the Host computer's settings;

  3. The AsfWriter opens a file and begins writing ASF data to it. Defining the AsfWriter's filename is mandatory and will produce an error if none is provided. Fortunately, although opening the file is compulsory, writing to it is not. By using this "loophole" we are able to trick the AsfWriter and simply produce a file of zero-bytes length which can be deleted when the FilterGraph is stopped.

Let's add a CheckBox (Don't write file) to our form...

If we use Delphi's Code Insight, we can examine the properties, functions and interfaces of the AsfWriter...

If we look at the IWMWriterAdvanced2 interface on the Microsoft website, we can examine the various methods it provides. The two we are interested in are GetSink and RemoveSink.

GetSink will provide us with a pointer to the file writer sink itself and, once we have the pointer, we can remove the writer (RemoveSink) and so prevent any data being written to the opened file.

IWMWriterSink is defined in \DirectX\WMF9.pas so WMF9 needs to be included in the uses section:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, DSPack, DSUtil, DirectShow9, WMF9;

procedure TForm1.ComboBox1Select(Sender: TObject);
var
   WriterSink:  IWMWriterSink;
begin
   if FilterGraph1.Active then FilterGraph1.Active:= False;
   FilterGraph1.ClearGraph;

   Filter1.BaseFilter.Moniker:= VideoDev.GetMoniker(ComboBox1.ItemIndex);
   FilterGraph1.Active:= True;
   VideoWindow1.FilterGraph:= FilterGraph1;
   Filter1.FilterGraph:= FilterGraph1;
   FilterGraph1.Mode:= gmCapture;
   AsfWriter1.FilterGraph:= FilterGraph1;
   AsfWriter1.Filename:= OutputFile;

   with FilterGraph1 as ICaptureGraphBuilder2 do
   begin
      RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter1 as IBaseFilter,
                     nil, VideoWindow1 as IBaseFilter);
      RenderStream(@PIN_CATEGORY_CAPTURE , nil, Filter1 as IBaseFilter,
                     nil,  ASFWriter1 as IBaseFilter);
   end;

   if CheckBox1.Checked then
   begin
      AsfWriter1.WriterAdvanced2.GetSink(0, WriterSink);
      AsfWriter1.WriterAdvanced2.RemoveSink(WriterSink);
   end;
   
   FilterGraph1.Play;
end;

The zero-bytes file can be cleaned away in the Form's OnCloseQuery event handler...

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
     if FileExists(OutputFile) then
        DeleteFile(OutputFile);
end;


Profiles

Here's our project streaming across the network.. Well, it's on the same PC but it is being streamed across to Windows Media Player. If you've tried to change the AsfWriter Profile to improve the picture quality, you'll already know that only a couple of them seem to work - the rest produce an "Unspecified error ($80004005)". So, what's the problem and how can we fix it? Now that we can run the project for some time without filling our Hard Drive with an ASF file, we'll have a look at Profiles in the next section.

previous page | next page

1 | 2 | 3 | 4 | 5 | 6 |


This site and its contents are © Copyright 2005 - All Rights Reserved.