Filiep

Hi, let me explain what I am trying to do.
I wrote a program to extract Teletext subtitles from DVR-MS files.
As I do not understand the whole Directshow stuff, C#, etc., I tried to avoid it as much as possible.
What I did was link pin2 of a DVR-MS file that contains teletext information to a Directshow dump filter using Graphedit.
That way, I got a large file, that contains all of the Teletext data.
Next, I wrote some decryption routines in Freebasic and finally, I parse the decrypted file for subtitles, again in Freebasic.
The result I get is an SRT file with subtitle and colour information.
The problem of course is the timings.
Simply dumping the data to a large file, does not tell me WHEN a certain subtitle was displayed.
I thought this would not be a big problem, as Teletext normally shows a clock on the screen.
However, what I found was that :

* the clock only displays data up to the second level, so that 19:52:08 could be anything between 19:52:08,000 and 19:52:08,999
Therefore, the program has lots of issues with getting the timings right, especially for live programs.
Also, sometimes the clock is simply not displayed, or that area is being abused for scrolling commercial texts.

So although the program works quite well, I would like to improve it with more accurate timings.
Is there any way of using Graphedit to create a dump file that contains some kind of marker every time a certain period of time has passed.
So, for example :

<Teletext data
..
.
.
.
>
<!!!New video frame starts here!!!>
<Teletext data
..
.
.
.
>

etc.


That way, I would get 50 markers per second (PAL) in the dump file, and instead of calculating relative time based on the text clock that is being displayed in my Freebasic program, I could simply start the time at 00:00:00,000 and for each time I find a marker I could simply add 20ms to the current time.
Any subtitles I would find there would then start at that time interval.

So from the many searches I did, if you were to program this, you would need to read the file synchronously (with the video ) and use some kind of synchronous equivalent to the normal dump filter.

Does anyone know a way of doing this without writing lots of code in Directshow




Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

You need to do a little bit of DirectShow code. As you managed to compile the Dump filter that would be what I work from.

You need to create a modified Dump filter that either adds the timestamp data to the output file or to a secondary file.

Every time there is a sample received on the Dump filter's input pin there is a time stamp attached. It is not an actual time, but rather a relative time from the start of the stream. The time stamp is accurate to 1/10000 of a second.

The data is received in CDumpInputPin::Receive(). By default the time stamp is read and optionally output for debugging purposes, but nothing else is done with it. It would seem that you could easily extend this to write out another file that contains a list of times and data file offsets for use in your post processing.

All this presumes that the samples on this pin are actually time stamped, which presumably they are.






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

There 's a bit of a misunderstanding there.
I have not written any Directshow code yet.
I used Graphedit and manually connected the pins to produce the output file, and in the manual for my utility I 'm telling people to go about it that way, though I realise this is far from ideal.
I did find some ready made code in the WMSDK, but there they only connect video and audio pins, it 's like they try to avoid doing anything with closed captions or subtitles.
I 'm talking about the WMSYNCREADER sample in the WMFSDK11.
Do you know that code and whether it would be hard to adapt it so I could dump the third stream (non-video, non-audio)




Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

The procedure would be exactly the same with the IWMSyncReader object in the Format SDK. Simply call GetNextSample() on this stream and you will receive chunks of timestamped data, process it any way you wish. See the sample in the documentation called "Reading Files with the Synchronous Reader", simply change the stream number from 0 to the actual stream number you are looking for.




Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

OK, I 'll give it a try.
But I have an additional question on that :

Is it possible to create such a program with the Free edition of Visual C++ (I guess that would be Visual C++ 2005 Express Edition ).
In other words, will I have all the libraries, etc. that are necessary for running that demo sample, or do I need additional libraries that are maybe only available in more extended (pay) versions
As I mentioned before, I want to keep my software freeware.




Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

AFAIK there are no additional library requirements. I use the Express Edition occasionally and don't recall any problems.






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

Unfortunately, I am unable to compile even the simplest example I find on the internet.

For example : this one, which is literally what I found on MSDN : (http://msdn2.microsoft.com/en-us/library/aa390682.aspx)
What I do is, I create a new project, then add this cpp file which I call test.cpp, and then try to compile it.
I assume that though this is example code, that you still need to add some extra lines of codes to it, for inclusions of files or something, maybe a main function
It 's just that my knowledge of C++ is very limited.
I think if I could get this to compile, I could tinker enough to get it to do what I need to.
I get errors : "
.\TTsubripper.cpp(2) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\TTsubripper.cpp(2) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\TTsubripper.cpp(2) : error C2065: 'NULL' : undeclared identifier
.\TTsubripper.cpp(3) : error C2143: syntax error : missing ';' before '*'
.\TTsubripper.cpp(3) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\TTsubripper.cpp(3) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\TTsubripper.cpp(5) : error C2146: syntax error : missing ';' before identifier 'cnsSampleTime'
...
"
That is after I added #include "stdafx.h" first (before it simply would not compile at all)

IWMSyncReader* pSyncReader = NULL;
INSSBuffer* pMyBuffer = NULL;

QWORD cnsSampleTime = 0;
QWORD cnsSampleDuration = 0;
DWORD dwFlags = 0;
DWORD dwOutputNumber;
HRESULT hr = S_OK;

// Initialize COM.
hr = CoInitialize(NULL);

// Create a synchronous reader.
hr = WMCreateSyncReader(NULL, WMT_RIGHT_PLAYBACK, &pSyncReader);

// Open an ASF file.
hr = pSyncReader->Open(L"c:\\somefile.wmv");

// TODO: Identify the properties for each output. This works
// exactly as it does with the asynchronous reader.

// Specify a playback range from frame number 100 of the video
// stream to the end of the file. Assume that the video stream
// is stream number 2.
hr = pSyncReader->SetRangeByFrame(2, 100, 0);

// Loop through all the samples in the specified range.
do
{
// Get the next sample, regardless of its stream number.
hr = pSyncReader->GetNextSample(0,
&pMyBuffer,
&cnsSampleTime,
&cnsSampleDuration,
&dwFlags,
&dwOutputNumber,
NULL);

if(SUCCEEDED(hr))
{
// TODO: Process the sample in whatever way is appropriate
// to your application. When finished, clean up.
pMyBuffer->Release();
pMyBuffer = NULL;
cnsSampleTime = 0;
cnsSampleDuration = 0;
dwFlags = 0;
dwOutputNumber = 0;
}
}
while (SUCCEEDED(hr));

pSyncReader->Release();
pSyncReader = NULL;





Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

Try this. Use a new console app as the starting point. Make sure you have added the WMF SDK library and include paths to Visual Studio.

Code Snippet

#include "stdafx.h"

#include <wmsdk.h>

#pragma comment(lib, "wmvcore.lib")

int _tmain(int argc, _TCHAR* argv[])

{

IWMSyncReader* pSyncReader = NULL;

INSSBuffer* pMyBuffer = NULL;

QWORD cnsSampleTime = 0;

QWORD cnsSampleDuration = 0;

DWORD dwFlags = 0;

DWORD dwOutputNumber;

HRESULT hr = S_OK;

// Initialize COM.

hr = CoInitialize(NULL);

// Create a synchronous reader.

hr = WMCreateSyncReader(NULL, WMT_RIGHT_PLAYBACK, &pSyncReader);

// Open an ASF file.

hr = pSyncReader->Open(L"c:\\somefile.wmv");

// TODO: Identify the properties for each output. This works

// exactly as it does with the asynchronous reader.

// Specify a playback range from frame number 100 of the video

// stream to the end of the file. Assume that the video stream

// is stream number 2.

hr = pSyncReader->SetRangeByFrame(2, 100, 0);

// Loop through all the samples in the specified range.

do

{

// Get the next sample, regardless of its stream number.

hr = pSyncReader->GetNextSample(0,

&pMyBuffer,

&cnsSampleTime,

&cnsSampleDuration,

&dwFlags,

&dwOutputNumber,

NULL);

if(SUCCEEDED(hr))

{

// TODO: Process the sample in whatever way is appropriate

// to your application. When finished, clean up.

pMyBuffer->Release();

pMyBuffer = NULL;

cnsSampleTime = 0;

cnsSampleDuration = 0;

dwFlags = 0;

dwOutputNumber = 0;

}

}

while (SUCCEEDED(hr));

pSyncReader->Release();

pSyncReader = NULL;

}






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

Almost got this example working (I feel really stupid with all these beginners questions).
What I did to get it almost running is change the

#include <wmsdk.h>

to the full path where the wmsdk.h is located.

I then got an error that windows.h could not be found.

I did a search and found that this file is part of the Microsoft Platform SDK, so I installed that one as well.

Then I copied all those .h files to the folder where the other ones were.

Upon compiling it got an error each time, for a particular .h file, so I changed those from #include <filename.h> to #include "filename.h"

I had to do that a lot of times.

Eventually I got no more of this type of error, and I was left with one error :



.\test2.cpp(5) : error C2061: syntax error : identifier '_TCHAR'



I tried changing the "int _tmain(int argc, _TCHAR* argv[])" to an int_main() without parameters, but then the compiler complained that the parameters are mandatory :


test2.cpp(75) : error C4716: '_tmain' : must return a value


If you wish, I can ask this by private mail, as I am probably asking all kinds of beginner's C++ IDE questions.





Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

You are creating a big mess by copying all those files around, that is not the way to do it.

In your Visual Studio menu go to Tools -> Options -> Expand Projects and Solutions -> VC++ Directories. In the drop down select Show directories for: select Include Files. Add the path that points to the folder containing the Platform SDK include files. Do the same for the library files.

You should be using the Windows Vista (RTM) SDK as it contains the WMF11 SDK.






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

OK, I followed your advice once more (thanks for the patience).
So I installed Visual Studio Express C++ on my Vista machine.
I also installed the very large IMG with the RTM Vista Windows SDK.
I added the folder where the wmsdk.h is located, both in the libary and in the header section.

But strangely enough when I load this sample, I still get the same error :

1>------ Build started: Project: TTSubripper, Configuration: Debug Win32 ------
1>Compiling...
1>TTSubripper.cpp
1>.\TTSubripper.cpp(8) : error C2061: syntax error : identifier '_TCHAR'






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

Try adding #include <tchar.h>






Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Filiep

That seemed to take away that error, but now I get two different ones :

error LNK2028: unresolved token (0A00002B) "extern "C" long __stdcall CoInitialize(void *)" ( CoInitialize@@$$J14YGJPAX@Z) referenced in function "int __cdecl wmain(int,unsigned short * * const)" ( wmain@@$$HYAHHQAPAG@Z)
error LNK2019: unresolved external symbol "extern "C" long __stdcall CoInitialize(void *)" ( CoInitialize@@$$J14YGJPAX@Z) referenced in function "int __cdecl wmain(int,unsigned short * * const)" ( wmain@@$$HYAHHQAPAG@Z)







Re: DirectShow Development Getting time codes for analog Teletext ripper program.

Chris P.

Make sure you have ole32.lib in your project's additional library dependencies.

You can always reference the SDK documentation to find out which library is required for a particular function.