Monday, April 21, 2008

Problems Faced in registering the Filter DLL in Windows CE

Problems Faced in registering the Filter DLL in Windows CE:
-----------------------------------------------------------
I faced the problem in registering the DLL ;
Solution:
-----------
There is no such file to register the DLL in Windows Mobile Emulator evnvironment like regsvr32 ;
So I developed the my own version of RegSvr32 application with the help of MSDN KB Code;
My Register application will do the following:
1.Loads the DLL
2.GetProcAddress() fn to get the address of the "DllRegisterserver" and call it;
3.Unloads the DLL;
Now it was registered in to the registry;








Because the .def file is not included in DLL project input; what it means was
within this .def file we specified the DLL functions as follows:
DllRegisterServer
DllUnRegisterServer
Then only we will get the correct address of the DllRegisterServer fn. otherwise we will get Null pointer;



One More problem I faced while calling the DllRegisterServer() fn address from My Register application:
The application was hanged and not giving any error, I got the execption within that fn;
I am not able to figure out the problem;


Solution:
-------------
So I checked the MSDN documentation as follows:
For Windows CE,we need to do the following:
STDAPI DllRegisterServer()
{
return AMovieDLLRegisterServer( );// Windows Desktop- AMovieDLLRegisterServer2(TRUE) - these are not supported in WinCE
}
STDAPI DllUnregisterServer()
{
return AMovieDLLUnRegisterServer( ); //Windows desktop-AMovieDLLRegisterServer2(FALSE)to unregister-these are not supported in WinCE
}
However, within DllRegisterServer and DllUnregisterServer you can customize the registration process as needed.
One more thing we need to
CFactoryTemplate g_Templates[] =
{
{
g_wszName, // Name.
&CLSID_SomeFilter, // CLSID.
CSomeFilter::CreateInstance, // Creation function.
NULL,
&sudFilterReg // Pointer to filter information.
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

LPAMOVIESETUP_FILTER CSomeFilter::GetSetupData() //we must implement this one for Windows CE
{
return (LPAMOVIESETUP_FILTER) & sudFilterReg;
}

Saturday, April 19, 2008

Windows CE Directshiw Filter Error

Windows CE Directshow Filter Error :
-------------------------------------
I developed the Ball Source filter in Windows CE;
I got these errors:
Creating library Pocket PC 2003 (ARMV4)\Release/Ball_Filter.lib and object Pocket PC 2003 (ARMV4)\Release/Ball_Filter.exp
1>fball.obj : error LNK2019: unresolved external symbol "public: __cdecl CSourceStream::CSourceStream(wchar_t *,long *,class CSource *,wchar_t const *)" (??0CSourceStream@@QAA@PA_WPAJPAVCSource@@PB_W@Z) referenced in function "public: __cdecl CBallStream::CBallStream(long *,class CBouncingBall *,wchar_t const *)" (??0CBallStream@@QAA@PAJPAVCBouncingBall@@PB_W@Z)
1>fball.obj : error LNK2001: unresolved external symbol "protected: virtual long __cdecl CSourceStream::QueryId(wchar_t * *)" (?QueryId@CSourceStream@@MAAJPAPA_W@Z)
1>fball.obj : error LNK2019: unresolved external symbol "public: __cdecl CSource::CSource(wchar_t *,struct IUnknown *,struct _GUID)" (??0CSource@@QAA@PA_WPAUIUnknown@@U_GUID@@@Z) referenced in function "private: __cdecl CBouncingBall::CBouncingBall(struct IUnknown *,long *)" (??0CBouncingBall@@AAA@PAUIUnknown@@PAJ@Z)
1>fball.obj : error LNK2001: unresolved external symbol "public: virtual long __cdecl CSource::FindPin(wchar_t const *,struct IPin * *)" (?FindPin@CSource@@UAAJPB_WPAPAUIPin@@@Z)
1>fball.obj : error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::JoinFilterGraph(struct IFilterGraph *,wchar_t const *)" (?JoinFilterGraph@CBaseFilter@@UAAJPAUIFilterGraph@@PB_W@Z)
1>fball.obj : error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::QueryVendorInfo(wchar_t * *)" (?QueryVendorInfo@CBaseFilter@@UAAJPAPA_W@Z)
1>Pocket PC 2003 (ARMV4)\Release/Ball_Filter.dll : fatal error LNK1120: 6 unresolved externals


Solution Steps:
--------------------
I modified the things in "Release" Mode:

it may be due to calling convention mechanism;
But ARM doesnt have calling convention compiler option( /Gr, Gd,Gz);
Calling convention is applicable only to x86 machines now I am using ARM;

I doubt whether the Strmbase.lib is built in x86; if it is so means, Previously I developed the dshow Player application
with this same "strmbase.lib"; So there is nothing wrong in lib;
I closely watched the all the error fns; they are all contains wchar_t;
It may due to some unicode problem?
Solution:
----------
Project->Properties->C++ ->Language ->
Treat wchar_t as Built In Type:Yes

I just modified this property to No;
Treat wchar_t as Built In Type: No

Now all the linker errors are resolved;
Now I am not having any error;


Note:
---------
Even though I did all the above things in Debug Mode, I got the following error:
Creating library Pocket PC 2003 (ARMV4)\Debug/Ball_Filter.lib and object Pocket PC 2003 (ARMV4)\Debug/Ball_Filter.exp
fball.obj : error LNK2001: unresolved external symbol "public: virtual unsigned long __cdecl CBaseFilter::NonDelegatingRelease(void)" (?NonDelegatingRelease@CBaseFilter@@UAAKXZ)
Pocket PC 2003 (ARMV4)\Debug/Ball_Filter.dll : fatal error LNK1120: 1 unresolved externals
For Debug Mode:
I have added this code within the CSource derived class;
public:
STDMETHODIMP_(ULONG) NonDelegatingAddRef()
{
return InterlockedIncrement(&m_cRef);
}


//-----------------------------------------------------------------------------
// Decrement the reference count for an interface
// ////////////////////////////////////////
STDMETHODIMP_(ULONG) NonDelegatingRelease()
{
if(InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
Now it is working fine;

I have successfully build the filter code;

Friday, April 18, 2008

Audio and Video Port Problem in Audio Testing

RTP AMRTesting :
=================
1.I combined the multiple RTP packets in to a Single packet and passed it to the AMR Paser application;
2.Next added the AMR file extension and AMR start codes and try to play it with QT Player;
Created AMR file is wroking with QT Player; It is working.

3.Pls kindly check the Market Bit of the RTP header format;

if we are sending the audio and video thru INVC transcoder,I printed the RTP packet Number as follows:
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 60, Buffer size = 1389, Marker = 0
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 61, Buffer size = 1389, Marker = 0
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 62, Buffer size = 1389, Marker = 0
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 6, Buffer size = 28, Marker = 128
RTP packet Number = 63, Buffer size = 1389, Marker = 0

ffmpeg sends amr audio to RTP.I got the following:
RTP packet Number = 3, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 3
RTP packet Number = 4, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 4
RTP packet Number = 5, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 5
RTP packet Number = 6, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 6
RTP packet Number = 7, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 7
RTP packet Number = 8, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 8
RTP packet Number = 9, Buffer size = 1389, Marker = 0 HSB = 0 , LSB= 9


while sending audio and video we have the problem;One more thing if we send audio and video, QuickTime player is able to render the audio.


So without the packet number we need to do parsing;
Every Audio Frame Beginning is marked by the Marker bit as Zero;otherwise it will be 1 or TRUE;
If I developed the amr parser for this scenario, It causes the Screech Sound in audio with particular interval.At client side, I received the RTP packets and Dumped it into a file also givesthe same problem;

Solution:
-----------------

Finally I got the Solution:
we are sending video data at 5000 Port We are sending audio data at 5001 Port ;So it causes the problem;
Instead of it If I changed the things as
video as 4500 and Audio as 5000 means there will be no problem So Every RTP amr packet is having header Info;
For Audio and video There must be some difference.So that we can avoid this situation;

Thursday, April 03, 2008

Two types of AMR:

-----------------------

1.AMR or AMR_NB ( AMR narrow band) - Mono channels ( 8 bit audio)

2.AMR_WB ( AMR wide band) - stereo channels ( 16 bit audio)



we are using AMR_NB ;



Every AMR file begins with following Hex start codes:


23 21 41 4d 52 0a ( Equal string is: #!AMR.)


if we open the amr file, without these start codes means it will display like

---------------------------

Error

---------------------------

Error -2048: Couldn't open the file Quotes.amr because it is not a file that QuickTime understands.

---------------------------

OK

---------------------------

Every audio frame is having one byte frame header;


format is as follows:

---------------------------------------------

F ( 1 bit) | FT( 4 bits) | 1 ( 1bit)

---------------------------------------------




Frame Type

Mode

Frame Size(Including 1 byte header)

0

AMR 4.75

13

1

AMR 5.15

14

2

AMR 5.9

16

3

AMR 6.7

18

4

AMR 7.4

20

5

AMR 7.95

21

6

AMR 10.2

27

7

AMR 12.2

32



if we have a file with 12.2 kbps means, we can check this by the frame header;

and moreover we can note that every frame have 1 byte header;But it is same as start. Assume that first frame's header is 3C then every frame must begins with header start code ;

if the header is having proper start code and the next it will check whether every frame is having same header info; otherwise it will reports the error as follows:


"Quicktime media file is having incorrect duration"



I have to do one more check;

if every frame is having different header start code whether the QuickTime play that AMR file ?...


3C is a frame header for first frame;

38 is a frame header for second frame;

Both frame headers indicate the same Frame Type;

whether it will works ?


Result :

----------

it works fine;


Test case 2:

-------------------

Instead of 0x38, I inserted the 0x20.

Then I didnt get any sound while playing it in QuickTime player and moreover the Quicktime is not giving any errors;


Instead of 0x20, I made it as 0x20, then I faced the same problem.


Every AMR frame is having 20 ms of data;


So if 40 frames are available means


40 * 20 = 800 milli seconds( play time of that frames);


1000 milliseconds = 1 second

AMR over RTP:



RTP Packet Size 1389

RTP header size 12

--------

1377

-----------

(1377 / Frame Size) - 1 = Number of ToC Entries; each frame has ToC entry in RTP

Or just count the number of bytes (ToC entries) to identify the frames available in a RTP packet;



How can we extract the AMR mode information from the RTP packet?


First check the CMR (Codec Mode Request) .

It is having bandwidth. For Each bandwidth, the frame size is fixed;


CMR Mode Frame size (bytes)

0 AMR 4.75 13

1 AMR 5.15 14

2 AMR 5.9 16

3 AMR 6.7 18

4 AMR 7.4 20

5 AMR 7.95 21

6 AMR 10.2 27

7 AMR 12.2 32


Every AMR frame is having 20 ms of audio data;


So if 40 frames are available means


40 * 20 = 800 milli seconds (play time of that frames);


1000 milliseconds = 1 second


From Source Filter, Based on Number of Frames we need to set the Start and Stop timestamps.



AMR over RTP is as follows:


+----------------+-------------------+----------------

| payload header | table of contents | speech data ...

+----------------+-------------------+----------------



Payload header is 4 bits;

First 4 bits are CMR (Codec Mode Request); From Codec Mode Request value, we can identify the frame size;


ToC (Table of contents) -


Each and every frame has an entry for the ToC;


If RTP packet is having 43 audio frames means that much of Toc Bytes must be available.



After F0, Remove the same types of bytes; (this byte indicates the audio bit rate information)

But How can we know the Frame Type?




1011 1100 (BC) 12.2 kbps

1011 0100 (B4) 10.2 kbps

1010 1100 (AC) 7.95 kbps




RTP packet:

---------------


If a terminal has no preference in which mode to receive, it SHOULD set CMR=15 in all its outbound payloads


Each RTP AMR data begins with F0 and then ToC entries like 0xac, 0xbc, 0xb4 as repetitive.


If the RTP packet has N frames, RTP packet is having N number of TOC Entries.

From the TOC Entry we can define the frame size of the audio frame;



TOC Entry will be in the following form:

---------------------------------------------

F (1 bit) | FT (4 bits) | 1 (1 bit)

---------------------------------------------


1 0111 1 00 -12.2 kbps ( 0x BC)

1 0110 1 00 -10.2 kbps ( 0x B4)

1 0101 1 00 - 7.95 kbps ( 0x AC)


------------------------------------------------



FO BC BC BC BC BC BC BC BC BC 3C

After the TOC contents, the First start code acts as a frame header;


3C is the frame header available in an audio frame and every audio frame must begins with 3C;

From the bit rate, we can determine the Frame Size;


CMR Mode Frame size (bytes)

0 AMR 4.75 13

1 AMR 5.15 14

2 AMR 5.9 16

3 AMR 6.7 18

4 AMR 7.4 20

5 AMR 7.95 21

6 AMR 10.2 27

7 AMR 12.2 32


Frame Size is including a frame header;


But RTP packet is having the frames as follows:



First Frame alone has the 1 byte audio frame header; rest of the frames will not have header; we need to add it manually;


Ac 12 20 39 40 29 20 39 33



Ac is a frame header and from the header onwards we can identify the number of bytes per frame; assume that if the frame header info as 4.75kbps having frame size 13 means from the frame header, count the 13 bytes; then next insert the First frame’s frame header and count the 13 bytes from the header and then insert the frame header for 3rd frame;



1st Frame Header bytes After 13 bytes insert the First Frame’s header, then next insert the frame header after the 26 bytes and next insert the frame header after the 39 bytes. Do it repeatedly.

If we have not inserted the frame header at the every frame start, then it will be decoded by the AMR decoder but u will not have any hearable audio.

Wednesday, April 02, 2008

How to stream AMR to RTP and Play it in QuickTime

Use AMR file as source to stream AMR to RTP. ffmpeg -re -i "d:\media\vel1.amr" -acodec libamr_nb -ar 8000 -ab 12.2kb -ac 1 -f rtp rtp://192.168.1.198:5000/

it plays the audio in Quicktime.
AMR.SDP File contents:
-----------------------
v=0
o=Mass 3123312 121232 IN IP4 192.168.1.198
s=Rtsp Session
c=IN IP4 192.168.1.198
t=0 0
a=range:npt=0-
m=audio 5000 RTP/AVP 97
a=rtpmap:97 AMR/8000
a=fmtp:97 octet-align=1

Thursday, March 27, 2008

Important notes

Negotiating Pin Connections:
------------------------------------
When the Filter Graph Manager tries to connect two filters, the pins must agree on various things. If they cannot, the connection attempt fails. Generally, pins negotiate the following:
1.Transport
2.Media type
3.Allocator
Transport:
------------
The transport is the mechanism that the filters will use to move media samples from the output pin to the input pin. For example, they can use the IMemInputPin interface ("push model") or the IAsyncReader interface ("pull model").

Media type:
------------
Almost all pins use media types to describe the format of the data they will deliver.
Allocator:
--------------
The allocator is the object that creates the buffers that hold the data. The pins must agree which pin will provide the allocator. They must also agree on the size of the buffers, the number of buffers to create, and other buffer properties.
The base classes implement a framework for these negotiations. You must complete the details by overriding various methods in the base class. The set of methods that you must override depends on the class and on the functionality of your filter.

Processing and Delivering Data:
------------------------------------
The primary function of most filters is to process and deliver media data. How that occurs depends on the type of filter:
A push source has a worker thread that continuously fills samples with data and delivers them downstream.

A pull source waits for its downstream neighbor to request a sample. It responds by writing data into a sample and delivering the sample to the downstream filter. The downstream filter creates the thread that drives the data flow.
A transform filter has samples delivered to it by its upstream neighbor. When it receives a sample, it processes the data and delivers it downstream.
A renderer filter receives samples from upstream, and schedules them for rendering based on the time stamps.

Tuesday, March 25, 2008

RTP audio filter problem in latency...

1.Yesterday we completed the Packet loss adjusting mechanism.
2.Today we improved the audio quality. By Putting IAmPushSource and set the latency as
GetLatency(){ *plLatency = 3500000; return S_OK;}
I have implemented the IAMPushSource on My live source Filter's Output Pin.
I faced 2 to 3 seconds latency problem;
So I modified the things as follows:
STDMETHODIMP CRTPAudioStream::GetPushSourceFlags(ULONG *pFlags)
{
*pFlags = AM_PUSHSOURCECAPS_PRIVATE_CLOCK;
//The filter time stamps the samples using a private clock.
//The clock is not available to the rest of the graph through IReferenceClock.
return S_OK;
}
Now everything works fine within the Filter, we implemented as follows:

class CRTPFilter: public CSourceStream, public IAMFilterMiscFlags
{
public: // IAMFilterMiscFlags override
ULONG STDMETHODCALLTYPE GetMiscFlags(void)
{ return AM_FILTER_MISC_FLAGS_IS_SOURCE; }
};

class CRTPAudioStream : public CSourceStream,public IAMPushSource
{
public:
//IAMPushSource
STDMETHODIMP GetMaxStreamOffset(REFERENCE_TIME *prtMaxOffset)
{return E_NOTIMPL;}
STDMETHODIMP GetPushSourceFlags(ULONG *pFlags)
{ *pFlags = AM_PUSHSOURCECAPS_PRIVATE_CLOCK;return S_OK;}
STDMETHODIMP GetStreamOffset(REFERENCE_TIME *prtOffset)
{return E_NOTIMPL;}
STDMETHODIMP SetMaxStreamOffset(REFERENCE_TIME rtMaxOffset)
{return E_NOTIMPL;}
STDMETHODIMP SetPushSourceFlags(ULONG Flags)
{return E_NOTIMPL;}
STDMETHODIMP SetStreamOffset(REFERENCE_TIME rtOffset)
{return E_NOTIMPL;}
STDMETHODIMP GetLatency(REFERENCE_TIME *prtLatency)
{ * prtLatency = 45000000; return S_OK;} //Set 450ms Latency for audio
};

Saturday, March 15, 2008

CSource Filter architecture with memory mapped file

For Network Source Filter, we are not able to receive and render the data efficiently,if we want to implement any Queue like mechanism to network received packets and render the data if we did all these things in a source filter., that will takes much CPU time. So we can do it different way as follows:

within the source filter, we have to read data from the memory mapped file.From another one application, we have to read data from network and write it to the memory mapped file.But Both the Source Filter and Network receiving application must be resides in the same system. if we did like this, then we can render the received audio and video data without any problem. we can also queue the recceived network packets.

I have seen the application for the following: Source Filter renders the data in a memory mapped file.
1. Camera Source Filter to render the data from the memory mapped file.
2. From another application , it creates the Filter Graph with source Filter and implemented the Thread to receive packets from the network and Queueing it in a datastructure.

Add Worker Thread in Source Filter derived from CSource class

How to create threads within CSource derived class.
within PushDesktop Source Filter,I created the thread. within this thread, I incremented the integer.within FillBuffer() fn, I displayed the integer value.
ThreadProc() {
i++; SetEvent( m_hEvent); }
FillBuffer() { WaitForSingleObject( m_hEvent);
}
the following code is not working ;
ThreadProc() {
while(true) {
dwWaitObject = WaitForSingleObject(m_hStopEvent, 5);
if(dwWaitObject == WAIT_OBJECT_0) { return 0; }
i++;
SetEvent( m_hEvent);
}
}
FillBuffer()
{
WaitForSingleObject( m_hEvent);
}
ThreadProc() {
i++; SetEvent( m_hEvent); }
FillBuffer() { WaitForSingleObject( m_hEvent);
}

At every one second, the video renderer waits for data from the source Filter. So if u modify thedwWaitObject = WaitForSingleObject(m_hStopEvent, 5); as
dwWaitObject = WaitForSingleObject(m_hStopEvent, 2); then it is working.
we must not take that much of time ...
Try with one more thing:
ThreadProc() { ThreadCB(); }
ThreadCB() { WaitForSingleObject(); printf("\n sundar");
}

Wednesday, March 12, 2008

RTP Audio Source Filter Problem without Glitches

Solution for Removing Audio Glitches in a RTP Audio Source Filter
-------------------------------------------------------------------
1.Test the Timestamp of the large files.
- it is also having some strange values like Start Time : 40000 and End Time :0
2.Set only start Time and be the stop time always 0.3.Dump the RTP Packet within the file.( No Problem with audio data)4.Implement the IAMPushSource interface.
I tested the large MP2 file in GraphEdit :
------------------------------------------------
If I inserted the dummy filter before the MPEG1 Audio Decoder filter, I got the following :
Start Time : 28114700 Stop Time : 23998200 Diff : 4116500Another time I got it as follows:
Start Time :31588108 Stop Time :28454648
Differnece :3133460

If I inserted the Dummy Filter after the MPEg1 Audio Decoder, I got the timestamp values as follows:
Grabber Sample size is : 18432 Start Time :0 Stop Time :0
Grabber Sample size is : 18432 Start Time :960000 Stop Time :0
Grabber Sample size is : 18432 Start Time : 1920000 Stop Time : 0
For the RTP Source Filter I got the following:
----------------------------------------------- 1.If I inserted the dummy filter before the MPEG1 Audio Decoder filter, I got the following :
Start Time Stop Time 2520000 2520000 2520000 2835000 2835000 3150000 2.If I inserted the Dummy Filter after the MPEG1 Audio Decoder, I got the timestamp values as follows:
Grabber Sample Size is : 18432 Start Time : 2520000 Stop Time : 0
Start Time : 2835000 Stop Time : 0 Start Time : 3150000 Stop Time : 0
Start Time : 3465000 Stop Time : 0 Start Time : 3780000 Stop Time : 0
Nothing above is works.
Solution:
-------------------

I am sending mp2 audio data with 48Hz frequency. At the RTP Audio Source Filter, I modified the frequency as 22.05 ( 22050 samples per second)..

Samples per second is the speed controller of a filter graph. it determines the speed of the filter.

48000(48 KHz) filter will run fast.
44100 (44.1KHz) filter will be some extent slow compare to the 48000.
22050( 22.05 KHz ) is very slow.
we are rendering the audio half of the transmitted audio's speed.

Tuesday, March 11, 2008

RTP source Filter

RTP Source Filter :
---------------------
From RTP Source Filter, we will just call the APIs in RTP Stack DLL.
we called the RTP Stack DLL APIs as follows:

RTPReceiveVideo() ; if( HasMPEG4Frames() == TRUE)
{ GetMPEG4Frame(pbBufferdata,pbBufferSize,iTimestamp); }
within this RTP stack DLL, we implemented the RTP parser.
Normally only KeyFrames alone will be wrapped in more than one RTP packet.
So what we have done was if the frame is wrapped in more than one RTP packet, then will put it in some Queue.
if we received all the consecutive RTP packets until the end of that frame,then only we will return HasMPEG4Frames() as TRUE.otherwise we will discard that Packet.
Notes:
-----------
ffmpeg will sends every MPEG4 Encoded frame beginning in a new Packet.
if the Frame contained in more than one packets, assume that if the frame is in 3 RTP Packets. within the 3rd RTP packet it will notsend the Next Frame's data.it will be wrapped in 4th RTP packet.

MPEG4 Decoder Filter Problem

MPEG4 Decoder Filter:
----------------------
within MPEG4 Decoder Filter,we will allow only keyframe for the first time by Checking the following :
if( m_bFirstFrame)
{
if ( (pSourceBuffer[0] == (unsigned char) 0x0) && (pSourceBuffer[1] == (unsigned char) 0x0) && (pSourceBuffer[2] == (unsigned char) 0x1) &&
((pSourceBuffer[3] == (unsigned char) 0xB0) // VOS Start Code
((pSourceBuffer[3] ==(unsigned char) 0xB6) && // VOL with KeyFrame
( (pSourceBuffer[4] & 0xC0)== 0x00) )
(pSourceBuffer[3] == (unsigned char) 0x20)
) )
{
m_bFirstFrame = false;
}
else {
//Wait For KeyFrame
if (NOERROR == pSource->GetTime(&TimeStart, &TimeEnd))
{ pDest->SetTime(&TimeStart, &TimeEnd);
}
return NOERROR;
}
}

if we got the First frame, then we will send the data to the MPEG4 Decoder DLL APIs whatever we got from the RTP source Filter.

Note :
------------
MPEG4 Decoder DLL APIs support only frame by frame decompression.
That means at atime we can pass only one frame to the MPEG4 decoder DLL Apis. otherwise MPEG4 Decoder will fails.

Audio Source Problem

Description about the Audio Problem :
---------------------------------------
1.within the Audio source Filter we set the config as follows: i)Sampling Frequency is 48KHz ii) we set the timestamp as follows from the RTP packet as follows:
m_rtStart = m_rtStop; m_rtStop = m_iRTPPacketTimestamp ;
the difference between m_rtStart and m_rtStop is 15200.
AudioFrameNo StartTime Stop Time
1 0 15120
2 15120 30240
3 30240 45360 and so on
within the Source Filter, we dumped the received audio data to an Mp2 file without timestamp information. if we played the Mp2 file, it was working well.
2.ffmpeg command for capturing data from audio source as follows:
ffmpeg -f audio_device -i /dev/dsp -acodec -mp2 -ar 48000 -ab 64kb -f rtp rtp://192.168.1.198:5001/

Application Architecture and filter development ideas

Some Application architecture :
--------------------------------------
Client - Wrap the VLC player in a Client application and control it.
Server - wrap the ffmpeg and control it using server application
we can broadcast the things with Server and receive the things with client
RTSP Application Architecture
------------------------------
RTSP Client : wrap the live555 RTSP receiving.
RTSP server: Wrap the live555 server


For Hobby, Develop the Filters around these open source code then we will get more ideas.

Wednesday, March 05, 2008

MPEG4 Decoder Problem

Somewhere in the middle the MPEG4 Decoder is failed.
if we used the MPEG4 Decoder with the MPEG4 Demux , then there will be no problem.
But if we used it with the RTP Video Source Filter, then we got the problem.
Reason:----------- This is the problem with MPEG4 Decoder.if we used any DivX free decoder filter, then it is working well.if we are starting from the middle, then the RTP source Filter will not send the Keyframe first.This is the problem
Solution:
--------------
I modified the Decoder Filter code to accept it as follows:
For the First time, if we are receiving VOS header then only allow it to display . otherwise just drop the frame.By checking the VOS Start code (00 00 01 B0) But it is not working. It seems like the ffmpeg is not sending VOS header.
So I added the code to check for the VOL start code and frame type.
if (bFirstFrame)
{
if( VOS start code or ( VOL startcode and frametype == KeyFrame))
{
bFirstFrame = false;
}
else { return S_FALSE; //Drop the Frame. }
}

Video Rendering downstream Filter Problem

I am decoding an MPEG2 video stream with resolution of 704x480 to the YUY2 format type (using ffmpeg).
If I use the equation:
lSampleSize = pVIH->bmiHeader.biWidth * pVIH->bmiHeader.biBitCount * pVIH->bmiHeader.biHeight / 8
I get a sample size of 675840 bytes.
This is the same size of data I am getting from my decode routine for the resulting YUY2 image. By intercepting other samples coming from other decoders, it is apparent that the correct size of the media sample, when calling SetActualDataLength should be 737280. This number can be calculating from the same equation above if the width is incremented to a number divisible by 128. I've discovered enough to know that this is due to the stride requirement of the VMR.
My question is this... How do I know the stride requirement as it surely cannot always be 128?
And more importantly, how would I go about populating a DirectShow media sample buffer from a pointer to the raw bytes of YUY2 data which is 675840 bytes in length?
Result :
--------------
When your output pin connects to the video renderer's input pin, after CheckMediaType() and before DecideBufferSize(), the video renderer will call your QueryAccept() method with the adjusted biWidth (that is, biWidth will be the stride and rcSource.right-rcSource.left will be the width). You need to override QueryAccept() and save the adjusted media type, so you will know the correct stride and sample size (which you will need right after in DecideBufferSize()).
> And more importantly, how would I go about populating a > DirectShow media sample buffer from a pointer to the raw > bytes of YUY2 data which is 675840 bytes in length?
You copy 1 scanline at a time:
for(y = 0; y < height; y++)
{
source = buffer + y * width; target = sample + y * stride; memcpy(target,source,width*sizeof(pixel));
}

Thread Programming

Thread Programming :
--------------------------------
  I faced Threading problems.

I developed the thread for reading from Network :

 int ThreadProc() 
 {
  while(bRun)
  {
   ReadFromNetwork();
  }
  return 0;
  
 }

 if I put the above code, I am getting CPU time as almost 100%.
CPU doesnt execute other processes. I put a Sleep(100), So that the OS executes the other processes during the sleep of that  program.
Sleep(0) also gives timeslice to execute other process.
 

 


 while(1){ } or While(bRun) {}  is called as Busy loop technically.

 Technically they call it as Busy waiting or Spinning.

busy waiting or spinning is a technique in which a process repeatedly checks to see if a condition is true,
such as waiting for keyboard input or waiting for a lock to become available. It can also be used to delay execution for some
amount of time; this was necessary on old computers that had no method of waiting a specific length of time other than
by repeating a useless loop a specific number of times, but on modern computers with clocks and different processor speeds,
this form of time delay is often inaccurate and a sign of a naïve attempt at programming.

Alternatives to busy waiting:
-----------------------------------------
 Most operating systems and threading libraries provide a wide set of system calls which will block the process
on an event, such as lock acquisitions, timers, I/O availability, or signals. This is often the simplest, most efficient, fair, and
race-free way. A single call checks, informs the scheduler of the event it is waiting for, inserts a memory barrier where applicable,
and may perform a requested I/O operation before returning. Other processes can use the CPU while the caller is blocked.
The scheduler is given the information needed to implement priority inheritance or other mechanisms to avoid starvation.

 Busy waiting itself can be made much less wasteful by using a "delay" function found on most operating systems.
This puts a thread to sleep for a specified time, during which the thread will waste no CPU time.
 If the loop is checking something simple then it will spend most of its time asleep and will not waste a large proportion
of the available CPU time. It will still consume some CPU time though.

When busy waits are appropriate :
------------------------------------------------
 In low-level hardware driver programming, sometimes busy waits are actually desirable.
It is not practical to implement hardware interrupt-based signalling for every hardware device, particularly for devices
 that are seldom accessed. Sometimes it is necessary to write some sort of control data to a hardware device and
then read back some sort of status data, which is not valid until several, perhaps even tens of clock cycles later.
The programmer could call an operating system delay function, but more time would be spent simply performing the
 function call (let alone switching to an interim thread) than is required by the hardware. In such cases, it is common to
implement a busy wait that keeps reading the status data until it is valid. Calling a delay function in this case would actually
waste CPU time due to the comparatively large overhead involved in the function call and thread switching.

 For Some important Operations, we can set the ThreadPriority to Highest.This will improves the execution speed.

For Windows programming, we can do the following:

ThreadProc()
{
 While(true)
 {
  DWORD dwWait = WaitForSingleObject(m_hThreadStopEvent,5);
  if (dwWait == WAIT_OBJECT_0)  //ThreadStopEvent occurred
  {
   break;
  }

  ReadFromNetwork();
 }
  return 0;


The Description for the above code is as follows:
 it will waits for 5 milliseconds for ThreadStop Event. if this event occurs, the control comes out of the while loop.
other wise control will be in loop and will reads data from the network.
 whenever we want to comes out of the ThreadProc() fn just rise the ThreadStopEvent.

convert video to mobile phone formats

Hi,
    if ur mobile phone is supporting video formats.then u can convert the video to the mobile phone video formats.For this Conversion, if we use any freeware, they will watermark the video with their company name, logo or with URL.
 So How can we convert the video to mobile phone video format without any watermark;

 just download "ffmpeg for windows".

This Zip file will have ffmpeg.exe.

Using this ffmpeg we can convert any type of video to the Mobile phone video format;
just run the ffmpeg with the following arguments :

 ffmpeg -i "D:\Source.avi"  -f 3gp -vcodec mpeg4  -s 176x144 -acodec libfaac -ar 8000 -ac 1 -ab 12.2k "D:\Output.3gp"

"D:\source.avi" may be any type of video file avi, wmv or any type.


 

Friday, February 29, 2008

How to set the Maximum Packet Size for the UDP Socket Buffer Size ?

How to set the Maximum Packet Size for the UDP Socket Buffer Size ?

-------------------------------------------------------------------------------
#define UDP_TX_BUF_SIZE 32768

#define UDP_MAX_PKT_SIZE 65536

// set udp recv buffer size to at least the largest possible udp packet

//size to avoid losing data on OSes that set this too low by default.

int optlen = sizeof(tmp);

if (!getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, &optlen) && ( tmp <>

{ tmp = UDP_MAX_PKT_SIZE;

setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp));

}

Thursday, February 28, 2008

Source Filter without Timestamp will works?

Source Filter without Timestamp will works ?
within FillBuffer() fn of a source Filter, I have not set the timestamp .
But it is working well.Timestamp is necessary for storing the media( audio and video ) content to a file.
without Setting timestamp for the media sample, the Source Filter is working well.

Wednesday, February 20, 2008

How can we extract the MPEG4 Frame Type from the RTP packet ?

How can we extract the MPEG4 Frame Type from the RTP packet (I,P or B):
------------------------------------------------------------------------
We are creating a software to parse MPEG4 data. Can anyone tell me how to extract the Frame Type (I,P,B) frame type from the whole RTP packet?
I mean I have RTP packet with MPEG4 payload in it, then how to extract the Frame type information from it?
Solution :
---------------
vop_coding_type is encoded in the first 2 bits after vop_start_code.
vop_start_code is 00 00 01 b6 (hex)
vop_coding_type means:
0 0 -I VOP
0 1 -P VOP
1 0 -B VOP
1 1 -S VOP

we are sending mpeg4 video thru rtp using ffmpeg.
Every I Frame( KeyFrame) is having VOS start code. 00 00 01 B0

Monday, February 18, 2008

How can we achive the Dynamic Buffer size for the output pin of a Filter?

How can we achive the Dynamic Buffer size for the output pin of a Filter?:
---------------------------------------------------------------------------
within DecideBufferSize() fn, we have to allocate the maximum amount of memory.( if we know) it means the outputPin's media sample size is same as DecideBufferSize() memory size.
DecideBufferSize() fn - allocates 4000 bytes. then Each output media sample is having 4000 bytes of memory.Assume that Frame1 is having only 3000 bytes.For the rest of the 1000 bytes we have to fill it with zeroes.
ZeroMemory() fn is available to set the zero for specified buffer size.

Frame1 Output Sample:
Transform(IMediaSample* pInms,IMediaSample* pOutms){
BYTE* pbInputData; DWORD dwInputSize;
BYTE* pbOutputData; DWORD dwOutputSize; pInms->GetPointer(&pbInputData); dwInputSize = pInms->Getsize(); //3000
//Frame1 have only 3000 bytes of data. pOutms->GetPointer(&pbOutputData); dwOutputSize = pOutms->GetSize();
ZeroMemory(pbOutputData,dwOutputSize); memcpy(pbOutputData,pbInputData,dwInputSize); // only 3000 bytes are copied, the rest of the 1000 bytes are 0 }
we can use this mechanism for Resize filter .
we can allocate memory for the maximum resolution for the output pin.
1900x1400x3 - is the maximum resolution. For the Rest of the bytes just Fill them with zeroes.

Register the Protocol in Directshow

Register the Protocol for the Filter:
--------------------------------------
The objective is if we opened the protocol URL in a GraphEdit,we need to insert our filter and capture the data.
Example :
----------
I opened the RTP protocol as in GraphEdit as follows in Render URL option:
rtp://127.0.0.1:5000/
it must insert the Source Filter.
it is not having the separate Source Filter.
I developed the Source Filter. while rendering the RTP, I want to insert my filter.
what we need to do ?
---------------------
Develop the Registry setup for the RTP protocol with our source Filter
RTP.reg contents :
------------------
REGEDIT4
[HKEY_CLASSES_ROOT\rtp]@="RTP : Realtime Transfer Protocol""EditFlags"=hex:02,00,00,00"URL Protocol"="""Source Filter"="{fd501041-8ebe-11ce-8183-00aa00577da1}"
[HKEY_CLASSES_ROOT\rtp\DefaultIcon]@="c:\\Program Files\\Windows Media Player\\wmplayer.exe,0"
[HKEY_CLASSES_ROOT\rtp\QuickView]@="*"
[HKEY_CLASSES_ROOT\rtp\Shell]@=""
[HKEY_CLASSES_ROOT\rtp\Shell\open]"EditFlags"=hex:01,00,00,00
[HKEY_CLASSES_ROOT\rtp\Shell\open\command]@="C:\\Program Files\\Windows Media Player\\wmplayer.exe %1"
By double clicking this file we can link our source Filter with the RTP protocol.But In the source Filter we need to implement the IFileSourceFilter interface.
What I have done ? I implemented the IFileSourceFilter in a Ball Source Filter and need to insert this filter whenever the the RTP protocol is rendered. Then within Load and GetCurFile() fn we got the control in a source Filter.
If I opened the rtp stream in a Windows media player 9 ( wmplayer.exe) rtp://127.0.0.1:4000/,it is not working. But if I opened the rtp stream in windows media player 6( mplayer2.exe), it inserts the The ball filter and renders the data in a player.

mplayer2.exe
=============
How can we run the .reg file and modify the registry ?.
.------------------------------------------------------
start rtp.reg


Output of the RTP source Filter :
-------------------------------------
MEDIATYPE : MEDIATYPE_Video
Compression : DIVX
Width : 176
Height : 144

ffmpeg rate emulation for realtime streaming

we sent the MPEG4 Encoded data thru ffmpeg in a RTP stream.At receiver side, we are not getting the correct number of frames.( Sequence Number of the Frames highly differ).
Like After the RTP Packet (Sequence) number 1526, I got the number as 3600 or something.
ffmpeg sends the Entire data at with 5 minutes( which can be streamed around 30 mins).So there might be the chance for TCP/IP stack overflow. It may causes some packet loss.
(Real Time) if we are sending the video data as same as stream time,then there will be no packet loss. So we send the data to RTP stream using rate emulation ( -re ) command in ffmpeg.
Eventhough we are sending data with this one, we got the packet loss problem.
Check it with the Ethreal packet capture.
Capture RTP packets using Ethreal and RTP stack application at the same time.

Wednesday, February 13, 2008

How can we effectly use Media Detector

Media Detector (MediaDet)
The Media Detector (MediaDet) object retrieves format information and still frames from file sources. The Media Detector does not require the Filter Graph Manager to function. To create this object, call CoCreateInstance. The class identifier is CLSID_MediaDet.
To read Windows Media™ files, the application must provide a software certificate, also called a key. Register the application as a key provider through the Media Detector's IObjectWithSite interface. For more information, see
Unlocking the Windows Media Format SDK.
The MediaDet object exposes the following interfaces:
IMediaDet
IObjectWithSite


IMediaDet Interface
The IMediaDet interface retrieves information about a media file, such as the number of streams, and the media type, duration, and frame rate of each stream. It also contains methods for retrieving individual frames from a video stream. The Media Detector (MediaDet) object exposes this interface.
To obtain information about a file using this interface, perform the following steps:
Create an instance of the MediaDet object by calling CoCreateInstance. The class ID is CLSID_MediaDet.
Call IMediaDet::put_Filename to specify the name of the source file.
Call IMediaDet::get_OutputStreams to obtain the number of output streams in the source.
Call IMediaDet::put_CurrentStream to specify a particular stream.
Call any of the following methods:
IMediaDet::get_FrameRate
IMediaDet::get_StreamLength
IMediaDet::get_StreamMediaType
IMediaDet::get_StreamType
To retrieve a video frame, call IMediaDet::GetBitmapBits or IMediaDet::WriteBitmapBits. The returned frame is always in 24-bit RGB format.
Video Thumbnail feature can also be achieved by this Media Detector.

What is Motion JPEG ?

What is Motion JPEG ?
In multimedia, Motion JPEG (M-JPEG) is an informal name for multimedia formats where each video frame or interlaced field of a digital video sequence is separately compressed as a JPEG image. It is often used in mobile appliances such as digital cameras.

Monday, February 11, 2008

Display settings affected the Filter's RGB output

YV12 to RGB565 Filter is not working if theDesktop display settings have 32 bit mode.

YV12 to RGB565 Filter Gives output as RGB16 if the Desktop Mode is RGB16YV12 to RGB565 Filter Gives output as RGB32 if the Desktop Mode is RGB32Even though we set the Output Format as RGB16 for the YV12To RGB565 Filter, it is being set as RGB32.
if I developed the Filter with Output as RGB16, the display settings mode is as follows:
1.Based on display settings mode,The Output RGB format of the Filter will be determined Ex:
I developed the YV12To RGB565 Filter.It outputs RGB565 format. RGB565 format is working if the Display settings mode is as 16 bit mode.
But while I checking the Filter's Output Pin properties and it becomes RGB32 if Displaysettings mode is as 32 bit.

So I Checked the YV12ToRGB Filter's output format as RGB565 within CheckTransform() fn.if I checked like this, then I got the problem. The YV12ToRGB filter is not connected to the MPEG4 Decoder Filter.
How can we solve this issue ?
based on the Display settings mode, i set the output Buffer size as RGB 16 or RGB 32.

Display settings affected the Filter's RGB output

YV12 to RGB565 Filter is not working if theDesktop display settings have 32 bit mode.


YV12 to RGB565 Filter Gives output as RGB16 if the Desktop Mode is RGB16YV12 to RGB565 Filter Gives output as RGB32 if the Desktop Mode is RGB32Even though we set the Output Format as RGB16 for the YV12To RGB565 Filter, it is being set as RGB32.
if I developed the Filter with Output as RGB16, the display settings mode is as follows:
1.Based on display settings mode,The Output RGB format of the Filter will be determined Ex:
I developed the YV12To RGB565 Filter.It outputs RGB565 format. RGB565 format is working if the Display settings mode is as 16 bit mode.
But while I checking the Filter's Output Pin properties and it becomes RGB32 if Displaysettings mode is as 32 bit.

So I Checked the YV12ToRGB Filter's output format as RGB565 within CheckTransform() fn.if I checked like this, then I got the problem. The YV12ToRGB filter is not connected to the MPEG4 Decoder Filter.
How can we solve this issue ?
based on the Display settings mode, i set the output Buffer size as RGB 16 or RGB 32.

ffmpeg Command To convert the audio to mp2

ffmpeg Command To convert the audio to mp2 :
-------------------------------------------------
ffmpeg -i "D:\Media\Vel1.mpg" -vn -acodec mp2 -ac 1 -ar 22050 -ab 64k "D:\Media\vel1.mp2"

while opening the MP2 file in aGraphEdit , I got the following :

Vel1.mp2 -> MPEG-1 Stream Splitter (Audio)-> MPEG Audio Decoder -> Default Directsound Device.

By Default all the filters are available in Dshow as In-built.

what is MP2 audio ?

what is MP2 audio ?
MPEG-1 Audio Layer II (MP2, sometimes Musicam) is an audio codec defined by ISO/IEC 11172-3. An extension exists: MPEG-2 Layer II and is defined in ISO/IEC 13818-3. The file extension for files containing such audio data is usually .mp2. While it has largely been superseded by MP3 for PC and Internet applications, it remains a dominant standard for audio broadcasting as part of the DAB digital radio and DVB digital television standards.

Wednesday, February 06, 2008

How can we debug the Filter's with GraphEdit ?

How can we debug the Filter's with GraphEdit ?

within the Filter development project Do the following.

Put the Breakpoint in Transform() fn or where the breakpoint is needed.
Project->Settings->Debug ->Executable for Debug session as C:\DXSDK\Bin\DXUtils\graphedt.exe.

and Set the Working Directory as Filter Project's directory as follows :

D:\SampleApps\Directshow\MPEG4DecoderFilter

Now Press F5 this will launch the GraphEdit and insert our filter and run the Graph . u will get
the breakpoint debugging control.

YUV420P to YV12 format conversion

I converted the YUV420P to YV12 format using the following :


The YV12 format is essentially the same as YUV420p, but it has the U and V data reversed: the Y values are followed by the V values, with the U values last.Our output is YUV420P.

Our MPEG4 Decoder's output is YUV420P. So we need to convert it as
YV12. I used the following code to convert from YUV420P to YV12.

long ulNumberOfPixels = m_iWidth * m_iHeight;
long ulUVBufferSize = (m_iWidth * m_iHeight) /4;
unsigned char ch; for(long i = 0; i < ulUVBufferSize; i++)
{
ch = pbYUVData[ulNumberOfPixels + i] ;
pbYUVData[ulNumberOfPixels + i] = pbYUVData[ ulNumberOfPixels + ulUVBufferSize + i];
pbYUVData[ ulNumberOfPixels + ulUVBufferSize + i] = ch;
}

Resources are not Properly Released in DShow Transform Filter ...

Resources are not Properly Released in DShow Transform Filter ...

The EndStreaming() fn is not called properly to release the resources.Afterwards I looked on the Dshow MSDN CTransformFilter Docs.it is not EndStreaming() fn.
we have to implement StopStreaming() fn to release the Resources.
Next I got the error like this.
---------------------------
GraphEdit
---------------------------
Some filters reported an error while stopping. The graph may become unpredictable. Unspecified error (Return code: 0x80004005)
---------------------------
OK
---------------------------
So I put the breakpoint and checked the application.The cause of the Error is

BYTE* pbData;
without allocating memory to it,I released it as follows :

if(pbData) { delete[] pbData; pbData = NULL; }

it causes the failure in execution.
So if we are allocating the memory for the pointer, just set it as NULL during initialization.

How can we skip the frame in a Temporal Decoder Filter ?

How can we skip the frame in a Temporal Decoder Filter ?

I developed the Temporal Decoder filter. During Decoding, I am not able to get the temporal decoded data.
My Temporal Decoder filter developed by deriving a CTransformFilter class..

CTransformFilter's Transform() fn, if we are not having decoded data,
then we have to skip the Current Frame.

if we return S_FALSE within Transform() fn. it will skip the current frame.

Example :

HRESULT CTemporalDecoder :: Transform(IMediaSample* pSrc, IMediaSample* pDest)
{
return DecodeBuffer(Src,pDest);
}

HRESULT DecodeBuffer(IMediaSample* pSrc, IMediaSample* pDest)
{
BYTE* pbEncodedData;
pSrc->GetPointer( &pbEncodedData);

if Decode(pbEncodedData ) //doesnt return the DecodedBuffer
{
return S_FALSE; //Skip the Current Frame.
}
}

MPEG4 Frame Construction( Identify the Frame Size)

I have to construct the Frames from the Bytes.
I need to develop the class for this one. and I need to test it with MPEG4 Decoder SDK in MPeg4DecoderExe;
Algorithm For constructing frame from bytes :
-----------------------------------------------
1.Pass Bytes to the algorithm with size. Add these Bytes to the custom Buffer.
2.Check For the StartCode 00 00 01 B6 and count the number of Bytes and
check for the beginning of a new frame.
3.if we found a frame, copy and send it to the MPEG4FeedData() and removed the frame bytes from the custom Buffer.
4.Call the PullData() fn...

Tuesday, February 05, 2008

How can we idenitfy the FrameSize in m4v file?...

How can we idenitfy the FrameSize ?.

Starts From 0x00 00 01 B6 to
Next 0x00 00 00, We can calculate the Buffer Size. That is the Frame Size.


0000 01 B0 ...
00 00 01 B6...
00 00 01 xx

if XX is B6 then there is no problem...

if XX is other than B6, we have to take it as a header.

So Next I have to develop the application to frame the buffer.

Friday, February 01, 2008

DLL registration problem

I copied the PushSource Filter.

Push source FIlter has 3 Filters. PushPinBitmap, PushPinBitmapSet and PushPinDesktop.
I removed the code for PushPinBitmap, PushPinBitmapSet .


If I compile the filter, without error it is compiling. But the Problem is while registering the Filter(.ax file), I got the following error.
---------------------------
RegSvr32
---------------------------
DllRegisterServer in D:\PushSource.ax failed. Return code was: 0xc0000005 ( Unrecoverable Error)
---------------------------
OK
---------------------------

So the problem lies in DLL registration part.


CFactoryTemplate g_Templates[3] =
{ { g_wszPushDesktop, // Name

&CLSID_PushSourceDesktop, // CLSID
PushSourceDesktop::CreateInstance, &sudPushSourceDesktop } };

This is Factory template.

Solution :
-------------
I modified the CFactorytemplate array as follows :
CFactoryTemplate g_Templates[] // Note here
= { }

MPEG4's Maximum Frame Size

H.263 specifies maximum frame size by means of "BPPmaxKb" parameter.BPPmaxKb defines the maximum frame size in terms of 1024 bits units.The standard specifies table for BPPMaxKb, which is dependentresolution. For QCIF, value of BPPmaxKb is 64 units, which translatesinto 8 Kbytes.

Does any body know whether there is limitation for maximum H.263 framesize?
For mpeg4 simple profile QCIF the spec said:

ISO/IEC 14496-2:2003(E) \ Annex D: Video buffering verifier \ D.2 VideoRate Buffer Model Definition clause 10:

The number of bits used for coding any single VOP, di, shall not exceedk * 16384 bits, where k = 4 for QCIF and Sub-QCIF, k = 16 for CIF, k =32 for 4CIF, and k = 64 for 16CIF, unless a larger value of k isspecified in the profile and level definition.
For QCIF, k=4. So maximum encoded frame size should be 8k bytes.

RTP Source Filter or SDP Source Filter ?

Develop the Stories :

-----------------------

Way1 :

-------

1.Implement the IFileSourceFilter in RTP source filter

2.In IFileSourceFilter's Load() fn,Do the following:


i)if the VOS header is available, then Set this VOS header to MPEG2VIDEOINFO's dwSequenceHeader and Set the Media type MPEG2VIDEOINFO 's width and height and further informations


ii) Wait For voS or VOL header. if the VOS header is not available, then check for the VOL header. if the VOL header is available then Frame the VOS header based on VOL information and Hardcode the profile and level indication and construct the VOS header


3.Later convert it to Socket and Instead of RTP MPEG4 Source Filters, we may call it as SDP Source Filter. RTP Source Filter ? or SDP Source Filter ? There will be no RTP Source filter only SDP Source Filter? Combine more than one stream.


RTP Source Filter or SDP Source Filter ?

Develop the Stories :
-----------------------
Way1 :
-------
1.Implement the IFileSourceFilter in RTP source filter
2.In IFileSourceFilter's Load() fn,Do the following:

i)if the VOS header is available, then Set this VOS header to MPEG2VIDEOINFO's dwSequenceHeader and Set the Media type MPEG2VIDEOINFO 's width and height and further informations

ii) Wait For voS or VOL header. if the VOS header is not available, then check for the VOL header. if the VOL header is available then Frame the VOS header based on VOL information and Hardcode the profile and level indication and construct the VOS header

3.Later convert it to Socket and Instead of RTP MPEG4 Source Filters, we may call it as SDP Source Filter. RTP Source Filter ? or SDP Source Filter ? There will be no RTP Source filter only SDP Source Filter? Combine more than one stream.

Thursday, January 31, 2008

How to parse MPEG4 data over the RTP stream and identify the header with SDP file ?

analysing the RTP received packets from middle of the sending and test the SDP with QuickTime and VLC player.
Qt and VLC plays the RTP stream thru SDP file .So There might be two chance for it.

1.without SDP file players can't receive RTP stream data.
Reason :
If I opened the RTP stream in a VLC player, it doesnt receive RTP stream data and gives unable to open error.

2. So based on this SDP file and we have to search for the VOL_start_code. For Each frame VOP is available. Successive VOPs can have I Frame or P Frame. for computer video, VOL_Header must have an information about Width and height

So combine the VOP information and SDP file information, it creates the header for MPEG4 Encoded data. But VOP start Code is not like that... 0000 01 B6 (vop_start_code ) it is available in more than one RTP packet consecutively.These packets are having less frame size.

VOL header is having more video Info . So it is having the header info. So we have to search for the Next VOL header.
if we started from middle of the RTP stream.

How to create memory for IMediaSample Queue ?

we can create the Object for the IMediaSample as follows :
typedef IMediaSample* PIMediaSample;
//For Memory allocation PIMediaSample *pSamples = new PIMediaSample[100];
//For Memory Release delete[] pSamples;

For Queue for the Output Pin, we can use COutputQueue class or we can use Queue

Queue <> samplesQ;
BYTE* pbData,*pbFrameBytes;
unsigned long FrameSize;
PIMediaSample* pSample = new PIMediaSample();
pSample->GetPointer(&pbData); memcpy(pbData,pbFrameBytes,FrameSize);
samplesQ.Push(pSample);

PIMediaSample* pSample; samplesQ.Pop(pSample); //Sample is Removed from Queue Deliver(pSample); pSample->Release(); // Here the sample is released.

otherwise we may use COutputQueue. It supports queueing of Media Samples.
COutputQueue * pOutputQueue;

How to Receive RTP Stream in the middle of The Transmission ?

Currently we must receive RTP Stream from Start Onwards...
Then only it will works correctly.otherwise it may not work out.So Do this Excercise :
1.Receive the RTP Stream from Middle of Transmission and dump it into a file.
2.Pass this dump file to the ffmpeg and decode it by specifying the Profile-level-id and specify the format as m4v and can see if we can specify theES.
ffmpeg also decodes the .m4v file well.


Previously I thought of it as SDP file can be played only with QuickTime.QuickTime is having some kernel based capture driver to receive data from socket.Actually QuickTime processes are running in background.But now it is not like that.But Later I played the SDP file with VLC player. VLC player doesnt have an exe file running in background.So we can play the MPEG4 video elementary stream from the middle of the sTream.Further Stream Infos are not needed.

SDP protocol, SDP file Format

SDP protocol :
----------------

.SDP file can be played in VLC player and Quicktime player.

So without any headers, How is it possible to decode the data ?
From Sample SDP file, what info we are getting ?.
1.MP4v -ES
2.IPaddress and Port to receive data
3.payload type ( 96)
4.profile-level-id ( argument passed to the MPEG4V-ES stream.)

Another way of Implementing the Distance Learning System

Instead of Filter based approach,
we can use the application approach also.

The application receives data from the Socket and send the received packets to the MPEG4 Decoder.From MPEG4 Decoder, we can get the raw yuv in 420P format.From Here we can convert it to RGB and render it in screen.

Filter needed for Distance Learning System

Filters Needed For Distance Learning System
:-------------------------------------------------
Based on RTP:
-----------------
1.RTP Video Sender Filter
2.RTP Video Receiver Filter
3.RTP Audio Sender Filter
4.RTP Audio Receiver Filter
5.MPEG4 Video Encoder Filter
6.MPEG4 Video Decoder Filter
7.MPEG4 Audio Encoder Filter
8.MPEG4 Audio Decoder Filter
9.Audio and Video Sync Filter


Based On RTSP:
------------------
1.RTSP Sender Filter
2.RTSP Receiver Filter
3.MPEG4 Multiplexer Filter
4.MPEG4 Demultiplexer Filter
5.MPEG4 Video Encoder Filter
6.MPEG4 Video Decoder Filter
7.MPEG4 Audio Encoder Filter
8.MPEG4 Audio Decoder Filter

Additional Features :
---------------------
1.MPEG4 Writer Filter for writing it into an MP4 File

Wednesday, January 30, 2008

How can identify the KeyFrame from a MPEG4 Encoded data ?

how can we identify the Keyframe from MPEG4 Encoded data ?...
within MPEG4 Encoded data, they will have the configuration information u know... Every vop_start_code(00 00 01 B6) indicates a new frame.
For the First Frame Set the KeyFrame flag. Count this vop_start_code to identify the key frame.
if the vop_start_code is 30, then FrameCount % number_of_vop_start_codes == 0 then it is a keyframe.

How can identify the KeyFrame from a MPEG4 Encoded data ?

how can we identify the Keyframe from MPEG4 Encoded data ?...
within MPEG4 Encoded data, they will have the configuration information u know... Every vop_start_code(00 00 01 B6) indicates a new frame.
For the First Frame Set the KeyFrame flag. Count this vop_start_code to identify the key frame.
if the vop_start_code is 30, then FrameCount % number_of_vop_start_codes == 0 then it is a keyframe.

How can we develop the Source Filter for RTP Receiver and set its media type ?...

How can we develop the Source Filter for RTP Receiver ?...
We can do one thing.

1.Develop the Source filter with Dynamic Output Pin,That means the output pin's buffer size may vary.

2.RTP receiver Filter must send the output data to its outptut pin based on the Frame. if the Frame is wrapped over more than one RTP packet, we have to send it over the network. For Doing this one develop the Separate class which will separate the RTP header and assemlble them as frame.
3.Look on MWS source Filter for Dynamic Output Pin.
GetStreamCount()
for(int i = 0; i < GetStreamCount(); i++)
{
StreamInfo stInfo = GetStreamInfo(i);
if(stInfo->id == VIDEO) { //Video is available in a Stream
stInfo->GetVideoFormat();
}
else if(stInfo->id == AUDIO)
{ //Audio is available in this stream stInfo->GetAudioFormat(); }
stInfo->GetExtraInfo() // Extra Header...
}
1.GetStreamInfo()
2.TrackId

VideoInfoHeader also must be set at the time of creating the Output Pin.

How can we idenify the MPEG2VIDEOINFO header's dwSequenceHeader from (received from RTP) MPEG4 Encoded buffer ?

How can we idenify the MPEG2VIDEOINFO header's dwSequenceHeader from (received from RTP) MPEG4 Encoded buffer ?

- Search for Group_of_vop_start_code (00 00 01 B3 check it without space ).Bytes Before the Group_of_vop_start_code is considered as a MPEG2VIDEOINFOHEADER's dwSequenceHeader.
From the Start of the VOS header's , we can identify the width and height of the video. otherwise we can hardcode the data with the specified configuration at the receiver side.

group_of_vop_start_code - 00 00 01 B3 -Search for 00 00 01 B3 Bytes before this code is added as a Header format;


MPEG2VIDEOINFO vidInfo;
vidInfo.dwSequenceHeader[0] = ( BYTE*) pbBytesBefore000001B3;
MPEG2VIDEOINFO vidInfo; BYTE* pbHeader = (BYTE*)vidInfo.dwSequenceHeader[0]

How can we idenify the MPEG2VIDEOINFO header's dwSequenceHeader from (received from RTP) MPEG4 Encoded buffer ?

How can we idenify the MPEG2VIDEOINFO header's dwSequenceHeader from (received from RTP) MPEG4 Encoded buffer ?

- Search for Group_of_vop_start_code (00 00 01 B3 check it without space ).Bytes Before the Group_of_vop_start_code is considered as a MPEG2VIDEOINFOHEADER's dwSequenceHeader.
From the Start of the VOS header's , we can identify the width and height of the video. otherwise we can hardcode the data with the specified configuration at the receiver side.

group_of_vop_start_code - 00 00 01 B3 -Search for 00 00 01 B3 Bytes before this code is added as a Header format;



MPEG2VIDEOINFO vidInfo;
vidInfo.dwSequenceHeader[0] = ( BYTE*) pbBytesBefore000001B3;
MPEG2VIDEOINFO vidInfo; BYTE* pbHeader = (BYTE*)vidInfo.dwSequenceHeader[0]

Tuesday, January 29, 2008

CMediaType Linker Error

I got the CMediaType Error as follows :

Creating library Debug/HDSceneDetectorAPI.lib and object Debug/HDSceneDetectorAPI.exp
CDxFilterGraph.obj : error LNK2001: unresolved external symbol "public: __thiscall CMediaType::CMediaType(void)" (??0CMediaType@@QAE@XZ)
CDxFilterGraph.obj : error LNK2001: unresolved external symbol "public: __thiscall CMediaType::~CMediaType(void)" (??1CMediaType@@QAE@XZ)
Debug/HDSceneDetectorAPI.dll : fatal error LNK1120: 2 unresolved externals


Solution :
-------------
For this problem, I included the "C:\DXSDK\samples\C++\DirectShow\BaseClasses\Debug_Unicode\strmbasd.lib"
in a Linker --> Input Settings...

Dynamic Output Pin Buffer size for the Filter _Look at DsNetwork Receiver Filter

Regarding Dynamic Output Buffer and size See the Things in DSNetwork Receiver Filter.DSNetwork Receiver Filter ouptuts dynamic buffer size on its output pin.DSNetwork filter implemented the allocator for the output pin.

Dynamic Output Pin Buffer size for the Filter _Look at DsNetwork Receiver Filter

Regarding Dynamic Output Buffer and size See the Things in DSNetwork Receiver Filter.DSNetwork Receiver Filter ouptuts dynamic buffer size on its output pin.DSNetwork filter implemented the allocator for the output pin.

How to decode the RTP MPEG4 dump( received bits) ?

How to decode the RTP MPEG4 dump :
-----------------------------------------
I added the Network receiver filter and dump the received data to a file.I send the rtp stream using ffmpeg as follows : ffmpeg -i "D:\highway.avi" -s 176x144 -vcodec mpeg4 -f rtp rtp://127.0.0.1:5000/
I got an error So I specified the audio as Nil using the following command : -an ffmpeg -i "D:\highway.avi" -s 176x144 -an -vcodec mpeg4 -f rtp rtp://127.0.0.1:5000/Now it is sending data to RTP successfully.
Using RTP receiver filter, I received the RTP data and dumped it to the file using Dump Filter.
I passed the RTP dump as input to the ffmpeg as follows :
ffmpeg -vodec mpeg4 -f rtp -i "D:\RTP.dump" -vcodec rawvideo "D:\RTP.YUV"
I played it with YUV file player, with some flickering it plays the RTP Mpeg data well.

How to Show the File Dialog before inserting a Filter

How to Show the File Dialog before inserting a Filter :
--------------------------------------------------------
if We implement the IFileSourceFilter or IFileSinkFilter then you will get a File Dialog...
While Inserting the filter in a GraphEdit.if we implement the IFileSourceFilter, the File Open Dialog box will be shown.if we implement the IFileSinkFilter, the File Save Dialog box will be shown.

Monday, January 28, 2008

MPEG4 .m4v file ( it is in raw format

Transport Stream :
----------------------
we opened the .mp4 file in a GraphEdit , 1.Dumped the MPEG2VideoInfo's dwSequenceHeader in to a file.
BYTE* pbData = (BYTE*) dwSequenceHeader[0];
cbSequenceHeader is having the size of the header. 2. Dumped the Encoded data in to a file.
Now we are creating a new file by merging a header and Encoded content.and Named it as .m4v , we can play this file in a media playerotherwise name it as .bits and we can decode this file using ffmpeg as follows :
ffmpeg -vcodec mpeg4 -i "EncodedWithHdr.bits" -vcodec rawvideo EncodedWithHdr.yuv
But Program stream and Transport Stream is not always same.

we can also create the .m4v by the following command :
ffmpeg -i D:\highway.avi -f m4v D:\highway.m4v

Program Stream and TransportStream Difference

There will be no difference between Program Stream and Transport stream. Except Header...

TS have VOS,VO and VOL headers. But the PS( Program Stream) is directly having VOL

headers. Sometimes we referred it as Elementary Stream.

if the Packet is having only video or audio, we call it as Elementary Stream.
if the packet contains both audio and video, we call it as Program Stream.
if the Packet contains one or more program stream we call it as Transport Stream.
we can carry more channels over the TS.

Thursday, January 24, 2008

ffmpeg RTP streaming


ffmpeg -vcodec mpeg4 -i D:\Media\vel1.mp4 -an -s 176x144 -vcodec rawvideo -f rtp rtp://127.0.0.1:5000/

while running this in a commandline, we got the following things in ffmpeg command informations.


I copied the following things in a rawvideo.sdp file and opened it in a
QuickTime player. Now the video is playing.


SDP:( this content will be generated by ffmpeg)
--------
v=0
o=- 0 0 IN IPV4 127.0.0.1
t=0 0
s=No Name
a=tool:libavformat
c=IN IP4 127.0.0.1
m=video 5000 RTP/AVP 96
a=rtpmap:96 MP4V-ES/90000
a=fmtp:96 profile-level-id=1




Tuesday, January 22, 2008

How to get the MPEG4 encoded bitstream headers within a MPEG4 Decoder Filter

1.I opened the ( highway176x144_30fps.mp4) file in a GraphEdit.

I dumped the MPEG encoded contents in to a file using the following graph:

MP4 Source Filter -> Sample Grabber Filter ->Dump Filter ( highway176x144_30fps.bits)

if I passed the dump file to the MPEG4 decoder application,It gives an error.
( Because the Encoded content also have some Header information ... It is missing )

2.I used my Temporal decoder filter to open the same Mp4 file ( highway176x144_30fps.mp4)

MP4 Source Filter -> Temporal Decoder Filter -> Video Renderer

within my temporal Decoder, I checked the MPEG2VIDEOINFO header of an Tempora Decoder filter's Input Pin.

MPEG2VIDEOINFo header is having some values like as follows:

DWORD cbSequenceHeader; // Size of the Encoded contents Header
DWORD dwSequenceHeader[1]; // Contains header info.

we can typecast it as follows to get the buffer,

BYTE* pbData =(BYTE*) mpg2VideoInfo->dwSequenceHeader;
I dumped this Encoded data to a file.( highway176x144_30fps.mpeg4hdr)


3.I created the Sample application to merge these two files.

The new File ( highway_mpeg4.bits) must have the following :

0. Create a new file ( highway_mpeg4.bits)
i. Append the contents of highway176x144_30fps.mpeg4hdr file to the highway_mpeg4.bits
ii. Append the contents of highway176x144_30fps.bits file to the highway_mpeg4.bits

4.Next I did the following.

Using FFMpeg to decode the MPEG4 contents as follows :

ffmpeg -s 176x144 -vcodec mpeg4 -i d:\media\MpegInput\highway_mpeg4.bits -vcodec rawvideo D:\media\MpegInput\highway_mpeg4.yuv

ffmpeg successully generated the Output file "D:\media\MpegInput\highway_mpeg4.yuv".


I Opened this YUV file in YUV player. it is working fine.

Thursday, January 17, 2008

How can we test the Temporal Decoder Filter Framework

How can we test the Temporal Decoder Filter Framework :
---------------------------------------------------------
1. For Temporal Decoder, the Input buffer size may vary...

So Implement the custom allocator for the input pin

2. Open Some Image file using OpenCV .
Based on the Image Size, allocate the Output pin buffer size using DecideBufferSize() fn.
copy the Image buffer in to the output buffer.

Thru this we can test the temporal decoder filter...

if we print the Input( source) Sample Size and Output(destination) Sample Size.
we can identify the variable Input Buffer size.

But the Output Buffer size is always constant.

Construct the Filter graph as follows in GraphEdit :

MP4 Video --> Temporal Decoder --> Video Renderer

Run the Graph if it runs the graph and displays the Image properly. then it is fine...

Error While Overriding virtual methods of Directshow Baseclasses

Error While Overriding virtual methods of Directshow Baseclasses:
---------------------------------------------------------------


while overriding some fns,
I got an error ...


class CMyTransformInputPin : public CTransformInputPin
{
public :
HRESULT Receive(IMediaSample* pSample);
};

HRESULT CMyTransformInputPin :: Receive(IMediaSample* pSample)
{
HRESULT hr = S_OK;
hr = CTransformInputPin::Receive(pSample);
return hr;
}


I got an error as follows :

error C2555: 'CTemporalInputPin::Receive' : overriding virtual function differs from 'CTransformInputPin::Receive' only by return type or calling convention
baseclasses\transfrm.h(33) : see declaration of 'CTransformInputPin'


Solution :
-------------

I modified it as follows :


class CMyTransformInputPin : public CTransformInputPin
{
public :
STDMETHODIMP Receive(IMediaSample* pSample); // Modification is Here...
};

HRESULT CMyTransformInputPin :: Receive(IMediaSample* pSample)
{
HRESULT hr = S_OK;
hr = CTransformInputPin::Receive(pSample);
return hr;
}

Now It is working.For STDMETHODIMP macro expansion is as follows :



#define STDMETHODIMP HRESULT STDMETHODCALLTYPE


For STDMETHODCALLTYPE macro defn is as follows :


#ifdef _68K_
#define STDMETHODCALLTYPE __cdecl
#else
#define STDMETHODCALLTYPE __stdcall
#endif


So it varies in calling convention, So I got an error...

GetMediaType() fn 's Execution in a DShow Filter

About GetMediaType() fn :
----------------------------
1. I opened the Image File in a GetMediaType() fn of a Temporal Decoder filter.
2. I added this filter to the GraphEdit as follows

Mp4 Video -> Temporal Decoder Filter ->Video Renderer
it is working fine ...
I saved this filter graph in .grf (graph) file.

If I opened the Graph(.grf ) file directly in GraphEdit, it gives error,

Because the GetMediaType() is not called in a filter. So The invalid memory is copied to my filter.

It causes the error in Graphedit while running the graph.

So instead of opening the Graph File,

Open the MP4 File in a graph edit and build the Graph manually every time as follows :


MP4 Video --> Temporal Decoder --> Video Renderer

GetMediaType() fn 's Execution in a DShow Filter

About GetMediaType() fn :
----------------------------
1. I opened the Image File in a GetMediaType() fn of a Temporal Decoder filter.
2. I added this filter to the GraphEdit as follows

Mp4 Video -> Temporal Decoder Filter ->Video Renderer
it is working fine ...
I saved this filter graph in .grf (graph) file.

If I opened the Graph(.grf ) file directly in GraphEdit, it gives error,

Because the GetMediaType() is not called in a filter. So The invalid memory is copied to my filter.

It causes the error in Graphedit while running the graph.

So instead of opening the Graph File,

Open the MP4 File in a graph edit and build the Graph manually every time as follows :


MP4 Video --> Temporal Decoder --> Video Renderer

How to develop only one custom Pin for a CTransformFilter

How to override only one Pin of a CTransformFilter?
-------------------------------------------------------

1.I want to implement the allocator for the Transform input pin.

How can we do this ?...


I developed my own CTransformInputPin derived class as follows :


class CMyAllocator : public CMemAllocator
{

};

class CNewTransformInputPin :public CTransformInputPin
{
friend class CMyAllocator;
};


I initialized my "CNewTransformInputPin" as follows :


class CMyTransformFilter : CTransformFilter
{
public:
CMyTransformFilter()
{
m_pInput = new CNewTransformInputPin();
}
};


while running the Graph, the GraphEdit hangs and I closed the application.

Solution :
-------------------

I modified it as follows :



class CMyTransformFilter : CTransformFilter
{
public:
CBasePin* GetPin(int i)
{
if( m_pInput == NULL)
{
m_pInput = new CNewTransformInputPin();
}

if( m_pOutput == NULL)
{
m_pOutput = new CTransformOutputPin();
}

if( i== 0) { return m_pInput;}
else if (i == 1) { return m_pOutput;}
else return NULL;
}
};





Now we can override the single Pin in a transform filter by Overriding the CBasePin* GetPin() fn...

Wednesday, January 16, 2008

Dynamic Buffer Size for input or Output Pin of a Filter

Things learnt today :
--------------------------
I want to identify the maximum MPEG4 Decoder's Input Buffer Size.

So what we need to do was

1.Open the MP4 file in a GraphEdit
2.GraphEdit is as follows :

MP4 Video Source Filter --> ffdshow video decoder --> Video Renderer

3.I developed the Null Transform Filter and which accepts any input media type and outputs the data on its output pin,
like a null transform filter and make the graph as follows :

MP4Video Source Filter --> Null Transform filter -> ffdshow video decoder --> Video Renderer

while running the graph, I am not getting video on video renderer and I got an error .

But it is not working well...

4.Next I removed the Null Transform filter and checked it with "Directshow Sample Grabber in DXSDK samples" filter.
it is working. So what I did was Just print the MediaSample size within a Directshow Sample grabber.

The Sample Grabber filter's media sample size is varying... Media Sample Size is not a fixed one.

How they managed it ? Null Transform filter accepts constant input size. So It causes the Error.


Conclusion :
--------------

To accept dynamic input size, we have to implement the custom allocator for the input pin.

Within the sample grabber filter, u may check this one...
Sample Grabber filter's input pin is using CMemAllocator class .

So if we want to develop the Encoder, the Encoder Output pin buffer size will be varying dynamically.
So we have to implement Custom allocator for output pins in Encoder.
if we want to develop the Decoder, the Decoder input pin buffer size will be varying dynamically.
So we have to implement custom allocator for input pins in Decoder.

Dynamic Buffer Size for input or Output Pin of a Filter

Things learnt today :
--------------------------
I want to identify the maximum MPEG4 Decoder's Input Buffer Size.

So what we need to do was

1.Open the MP4 file in a GraphEdit
2.GraphEdit is as follows :

MP4 Video Source Filter --> ffdshow video decoder --> Video Renderer

3.I developed the Null Transform Filter and which accepts any input media type and outputs the data on its output pin,
like a null transform filter and make the graph as follows :

MP4Video Source Filter --> Null Transform filter -> ffdshow video decoder --> Video Renderer

while running the graph, I am not getting video on video renderer and I got an error .

But it is not working well...

4.Next I removed the Null Transform filter and checked it with "Directshow Sample Grabber in DXSDK samples" filter.
it is working. So what I did was Just print the MediaSample size within a Directshow Sample grabber.

The Sample Grabber filter's media sample size is varying... Media Sample Size is not a fixed one.

How they managed it ? Null Transform filter accepts constant input size. So It causes the Error.


Conclusion :
--------------

To accept dynamic input size, we have to implement the custom allocator for the input pin.

Within the sample grabber filter, u may check this one...
Sample Grabber filter's input pin is using CMemAllocator class .

So if we want to develop the Encoder, the Encoder Output pin buffer size will be varying dynamically.
So we have to implement Custom allocator for output pins in Encoder.
if we want to develop the Decoder, the Decoder input pin buffer size will be varying dynamically.
So we have to implement custom allocator for input pins in Decoder.

Friday, January 11, 2008

How to call callback functions repeatedly ?

ll the callbacks will be in the form of as follows :

WSARecv( AsyncCallback);

if the data is received in a socket, AsyncCallback () fn is being called .
How can we repeatly Read data from socket ? By calling WSARecv() fn in a thread ( which is being called repeatedly)
?

No.. we can achive this by the following


WSARecv(AsyncCallback);


within AsyncCallback()
{

//call the WSARecv() fn based on some condition ...
}

For Example,

AsyncCallback()
{
if( bStop == false)
{
WsaRecv(AsyncCallback);
}
}



Another one way is :


bool bContinueLoop = true;
RecvSocket()
{
WSARecv(AsyncCallback);
}

AsyncCallback()
{
if(bContinueLoop)
{
RecvSocket();
}

}

StopRecvSocket()
{
bContinueLoop = false;
}

Monday, January 07, 2008

How to Implement DMO filters

Implement DMO filters :
-----------------------
1. if we want to develop the Inplace filter,

we have to implement IMediaObjectInPlace interface.

2. if we want to develop the filter like Transform Filter,

we have to implement IMediaObject interface.


Regards
Sundara rajan.A

calculate Time Between Two Frames using FrameRate

calculate Time Between Two Frames using FrameRate :
---------------------------------------------------
1.fDistanceBetweenTwoFrames = 1000 / FrameRate;
2.fDistanceBetweenTwoFrames = 33.33 for 30 FPS
3.fDistanceBetweenTwoFrames = 40 for 25 FPS

Thursday, January 03, 2008

Capture video and audio from devices and send it to RTP Stream

Capture video and audio from devices and send it to RTP :

1.I installed the cygwin in windowsXP.
2.I copied the FFMPEG with .exe
3. I connected the webcam,microphone in my pc.
4. I run this command in cygwin shell as follows :

$ ./ffmpeg -v 100 -f vfwcap -s "640x480" -i /dev/video0 -vcodec mpeg4 -f rtp rt
p://127.0.0.1:8090 -f audio_device -i /dev/dsp -acodec mp2 -f rtp rtp://127.0.0
.1:9090 2>&1 | tee ffmpeg_log_win32.txt


./ is the standard for running .exe files in cygwin shell.


we can switch over to drive using the following command:

cd D:
cd C:
we have to run the ffmpeg from the directory at which the it is being installed.


I opened the .sdp file in a QuickTime player.
After buffering the quicktime player shows the data.
SDP stands for Session Description Protocol.
.SDP file content is as follows :



v=0
o=- 0 0 IN IPV4 127.0.0.1
t=0 0
s=No Name
a=tool:libavformat
c=IN IP4 127.0.0.1
m=video 8090 RTP/AVP 96
a=rtpmap:96 MP4V-ES/90000
a=fmtp:96 profile-level-id=1
m=audio 9090 RTP/AVP 14
a=rtpmap:14 MPA/90000

I used the DS Network receiver to receive data from the specified port.
(8090) and using Dump Filter, I dumped the data in to a file.
FFMPEG transmits the data in Transport Stream format.
Our MPEG4 Encoder and decoders are in Program Stream.

Capture video and audio from devices and send it to RTP Stream

Capture video and audio from devices and send it to RTP :

1.I installed the cygwin in windowsXP.
2.I copied the FFMPEG with .exe
3. I connected the webcam,microphone in my pc.
4. I run this command in cygwin shell as follows :

$ ./ffmpeg -v 100 -f vfwcap -s "640x480" -i /dev/video0 -vcodec mpeg4 -f rtp rt
p://127.0.0.1:8090 -f audio_device -i /dev/dsp -acodec mp2 -f rtp rtp://127.0.0
.1:9090 2>&1 | tee ffmpeg_log_win32.txt


./ is the standard for running .exe files in cygwin shell.


we can switch over to drive using the following command:

cd D:
cd C:
we have to run the ffmpeg from the directory at which the it is being installed.


I opened the .sdp file in a QuickTime player.
After buffering the quicktime player shows the data.
SDP stands for Session Description Protocol.
.SDP file content is as follows :



v=0
o=- 0 0 IN IPV4 127.0.0.1
t=0 0
s=No Name
a=tool:libavformat
c=IN IP4 127.0.0.1
m=video 8090 RTP/AVP 96
a=rtpmap:96 MP4V-ES/90000
a=fmtp:96 profile-level-id=1
m=audio 9090 RTP/AVP 14
a=rtpmap:14 MPA/90000

I used the DS Network receiver to receive data from the specified port.
(8090) and using Dump Filter, I dumped the data in to a file.
FFMPEG transmits the data in Transport Stream format.
Our MPEG4 Encoder and decoders are in Program Stream.