GraphEdit File Format

94 views
Skip to first unread message

cairn

unread,
Feb 3, 2005, 9:15:02 AM2/3/05
to
I am reading in a .grf file into a IStorage, and then getting the data with
an IStream object. I am then using the IStream read to get the data in to an
array of bytes. This is then compacted by getting every other byte and
placing the result into a CString, but when I view the data I cannot see the
'CONNECTIONS' section of the file. I get the Filters section and then some
binary. Please could someone explain a good way to extarct all the data,
anothe way to get the data from the file so that we can do some processing on
it.


With Thanks.

Alessandro Angeli [MVP::DigitalMedia]

unread,
Feb 3, 2005, 2:12:22 PM2/3/05
to
[Sorry for the richtext, but I've used it to preserve the code formatting.]
 
Most likely you are parsing it wrong. Here is a full sample
parser:

--------- grfdump.cpp -------------------
#include <windows.h>
#include <errno.h>
#include <stdio.h>
 
#define TRACE(x) x
#define trace_open(x,y)
#define trace_close()
#ifdef UNICODE
# define trace wprintf
# define TRACEWSTR TEXT("s")
#else
# define trace printf
# define TRACEWSTR TEXT("S")
#endif
#define DWRESERVED 0
#define LPRESERVED NULL
#define TRACEHR_STR TEXT("0x%08lX")
#define TRACEHR_REF(hr) (hr)
 

#define LWS(c) ((c) == L'\n' || (c) == L'\r' || (c) == L'\t' || (c) == L' ')
 
LPWSTR token(LPWSTR p, LPWSTR* s1, LPWSTR* s2, WCHAR* q)
{
 for(; LWS(*p); p++);
 if(*q = *p == L'"' ? *p++ : L'\0') {
  for(*s1 = p; *p != *q; p++); *s2 = p++;
 } else {
  for(*s1 = p; !LWS(*p); p++); *s2 = p;
 }
 return p;
}
 
HRESULT skip(LPWSTR s1, LPWSTR* p)
{
 int n = wcstol(s1,NULL,10);
 if(n == 0 && errno == ERANGE) return E_FAIL;
 (*p)++; if(n > 0) *p = (LPWSTR)&((LPBYTE)(*p))[n];
 return S_OK;
}
 

int wmain(int argc, LPWSTR argv[])
{
 HRESULT  hr   = S_OK;
 IStorage* pGrfFile = NULL;
 IStream* pGrfData = NULL;
 STATSTG  rGrfStat;
 int   cb;
 LPWSTR  pb  = NULL;
 LPWSTR  s1, s2, p;
 WCHAR  q;
 
 TRACE(trace_open(NULL,zFalse));
 
 TRACE(trace(TEXT("*** StgOpenStorage(L\"%") TRACEWSTR TEXT("\")...\n"),argv[1]));
 if(S_OK != (hr = StgOpenStorage(argv[1],NULL,STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE,NULL,DWRESERVED,&pGrfFile))) goto exit;
 
 TRACE(trace(TEXT("*** OpenStream(L\"ActiveMovieGraph\")...\n")));
 if(S_OK != (hr = pGrfFile->OpenStream(L"ActiveMovieGraph",LPRESERVED,STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE,DWRESERVED,&pGrfData))) goto exit;
 
 TRACE(trace(TEXT("*** Stat()...\n")));
 if(S_OK != (hr = pGrfData->Stat(&rGrfStat,STATFLAG_NONAME))) goto exit;
 
 cb = (int)rGrfStat.cbSize.QuadPart;
 TRACE(trace(TEXT("*** new BYTE[%d]...\n"),cb));
 if(NULL == (pb = (LPWSTR)new BYTE[cb])) goto exit;
 
 TRACE(trace(TEXT("*** Read(%d)...\n"),cb));
 if(S_OK != (hr = pGrfData->Read(pb,(ULONG)cb,NULL))) goto exit;
 
 p = pb;
 
 p = token(p,&s1,&s2,&q);
 TRACE(trace(TEXT(">>> version = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
 
 p = token(p,&s1,&s2,&q);
 if(0 == wcsnicmp(s1,L"FILTERS",s2-s1)) {
  TRACE(trace(TEXT(">>> FILTERS\n")));
  while(TRUE) {
   p = token(p,&s1,&s2,&q);
   if(0 == wcsnicmp(s1,L"CONNECTIONS",s2-s1)) break;
   TRACE(trace(TEXT(">>>   %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     name .... = L\"%.*") TRACEWSTR TEXT("\"\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     class_id  = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   if(0 == wcsnicmp(s1,L"SOURCE",s2-s1) || 0 == wcsnicmp(s1,L"SINK",s2-s1)) {
    TRACE(trace(TEXT(">>>     file .... = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
    p = token(p,&s1,&s2,&q);
    TRACE(trace(TEXT(">>>     file_name = L\"%.*") TRACEWSTR TEXT("\"\n"),s2-s1,s1));
    p = token(p,&s1,&s2,&q);
   }
   TRACE(trace(TEXT(">>>     length .. = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   if(S_OK != (hr = skip(s1,&p))) goto exit;
  }
 }
 if(0 == wcsnicmp(s1,L"CONNECTIONS",s2-s1)) {
  TRACE(trace(TEXT(">>> CONNECTIONS\n")));
  while(TRUE) {
   p = token(p,&s1,&s2,&q);
   if(0 == wcsnicmp(s1,L"CLOCK",s2-s1)) break;
   if(0 == wcsnicmp(s1,L"END",s2-s1)) break;
 
   TRACE(trace(TEXT(">>>   %.*") TRACEWSTR,s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(" [L\"%.*") TRACEWSTR TEXT("\"]"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(" -> %.*") TRACEWSTR,s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(" [L\"%.*") TRACEWSTR TEXT("\"]\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     sample_size ........ = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     major_type ......... = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     subtype ............ = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     fixed_sample_size .. = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     temporal_compression = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     length(?) .......... = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     format_type ........ = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   p = token(p,&s1,&s2,&q);
   TRACE(trace(TEXT(">>>     length ............. = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
   if(S_OK != (hr = skip(s1,&p))) goto exit;
   p++; /// where is this L'\0' terminator documented??
  }
 }
 if(0 == wcsnicmp(s1,L"CLOCK",s2-s1)) {
  TRACE(trace(TEXT(">>> CLOCK\n")));
  p = token(p,&s1,&s2,&q);
  TRACE(trace(TEXT(">>>   required = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
  p = token(p,&s1,&s2,&q);
  TRACE(trace(TEXT(">>>   clock_id = %.*") TRACEWSTR TEXT("\n"),s2-s1,s1));
 }
 if(0 == wcsnicmp(s1,L"END",s2-s1)) {
  TRACE(trace(TEXT(">>> END\n")));
 }
 
exit:
 TRACE(trace(TEXT("*** hr = ") TRACEHR_STR TEXT("\n"),TRACEHR_REF(hr)));
 if(pb) delete [] (LPBYTE)pb;
 if(pGrfData) pGrfData->Release();
 if(pGrfFile) pGrfFile->Release();
 TRACE(trace_close());
 return hr;
}
-----------------------------------------



--

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net

Geraint Davies

unread,
Feb 3, 2005, 2:54:02 PM2/3/05
to

I didn't think that the internal format of .GRF files was documented at
all. In any case, I'm not convinced of the utility of GRF files except for
some specific test situations. Too much detail is stored in the file (media
types, pin names etc). What you really want to store in most cases is the
steps that you took to build the graph, not the detailed end result.

So I guess my helpful response is:
-- I'm not going to tell you because it's not documented
-- I wouldn't do it this way anyway

G

Alessandro Angeli [MVP::DigitalMedia]

unread,
Feb 3, 2005, 3:17:36 PM2/3/05
to
Geraint Davies wrote:

> I didn't think that the internal format of .GRF files was
> documented at all.

Actually, excluding a few mistakes in the published grammar,
it's documented in the SDK since v7 I think.

http://msdn.microsoft.com/library/en-us/directshow/htm/directshowgraphfileformat.asp

The March Hare [MVP]

unread,
Feb 3, 2005, 3:25:52 PM2/3/05
to
On Thu, 3 Feb 2005 19:54:02 +0000, Geraint Davies wrote:

> I didn't think that the internal format of .GRF files was documented at
> all. In any case, I'm not convinced of the utility of GRF files except for
> some specific test situations. Too much detail is stored in the file (media
> types, pin names etc). What you really want to store in most cases is the
> steps that you took to build the graph, not the detailed end result.
>
> So I guess my helpful response is:
> -- I'm not going to tell you because it's not documented

> -- *I wouldn't do it this way anyway* [emphasis added]

That's basically what has been recommended here in the past. You used to
be able to RenderFile a GRF file but, IIRC, that was removed at DX 8.1.

Reply all
Reply to author
Forward
0 new messages