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.

Friday, December 21, 2007

iQualityControl Notify Error

---------------------------
Hard coded break point
---------------------------
"IQualityControl::Notify not over-ridden from CBasePin. (IGNORE is OK)"
At line 2346 of C:\DXSDK\Samples\C++\DirectShow\BaseClasses\amfilter.cpp
Continue? (Cancel to debug)
---------------------------
Yes No Cancel
---------------------------
Solution :

This Error is displayed at runtime in a filter graph. So

for This Error I added the code as follows :
HRESULT Notify(IBaseFilter *pSelf,Quality q ) { return S_OK;}


in classes derived from CBasePin, Now it is working well...

Filter or DLL or .ocx registration Error

Filter or DLL or .ocx registration Error :
-------------------------------------------


Eventhough the DLL compiles and links well while registering the filter or DLL or.ocx using regsvr32 utility, I got this Error.

---------------------------
RegSvr32
---------------------------
.\Debug\HTTPWriterSinkFilterd.ax was loaded, but the DllRegisterServer entry point was not found.

.\Debug\HTTPWriterSinkFilterd.ax does not appear to be a .DLL or .OCX file.
---------------------------
OK
---------------------------

Solution Steps :
---------------


1.I Opened that DLL file in "Depends viewer" available in a visual studio tools
2. no function is exported from the DLL or filter file.
3.For Exporting the Functions, I used the .def file (module definition file).
4. Next I have opened the DLL,ax files in "Depends viewer" that are successfully registered
There the Dependency viewer displays the exported functions.
5. So the problem is in Exporting the functions
6. Next I opened the Project->Settings-> Linker->input ...

and I checked anywhere my .def file is specified there is nothing like that.

So I added the the following options

Project -> Settings-> Linker -> Input -> /DEF:My.def


Now I compiled the application and register it with regsvr32 utitily.
Now the registeration is done successfully .

if I opened that registered DLL in "Depends viewer", It displays the exported functions.

PostScript :
------------

In Some DLLs,even though they created the application as DLL,
without including this "/DEF:my.def", that dll also registers well.

Thursday, December 20, 2007

How to pass arguments from window to the windowProc function

How to pass arguments from window to the windowProc function :


CREATESTRUCT str;
int*i = new int();
*i = 40;
str->lpCreateParams = i;


WindowProc()
{
switch(Msg)
{

int* j = (int*) ((LPCREATESTRUCT(lParam)) ->lpCreateParams)

}
}


Another one way is we can also attach the Window parameter at the time of
WNDcLASS registration.

wc.cbWndExtra = i;

we can get this value using GetWindowLong()

int* j = (int*) GetWindowLong(hWnd,GWL_USERDATA);



SetWindowLong() fn is also available

we can also use GetWindowLongPtr() or SetWindowLongPtr() for this purpose.

Window Creation problem with WM_NCCREATE message

I registered the class in win32 SDK application.
I created the window using CreateWindow() fn.CreateWindow() fn returns NULL.
if I checked the GetLastError(), it returns 0( SUCCESS).window creation is failed but
GetLastError() also not returns valid Error information.
I handled the WM_NCCREATE message within a Window Procedure.


solution :

within the WindowProc() fn , I handled the WM_NCCREATE fn as follows :

case WM_NCCREATE :

break;



This is the reason for window creation failure. if we handled this WM_NCCREATE fn,
we must return TRUE. then only window creation will succeeds.

Friday, December 14, 2007

Identify the KeyFrame in a compressed input pin Filter

I developed the Netwriter Filter which accepts input as
Windows Media video.

within Netwriter Filter, how can we identify the KeyFrame ?

WMV is a compressed Format. How can we identify the Key Frame?

if the input pin of the transform filter is in compressed format,
How can we identify the KeyFrame ?...



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

Using IMediaSample's IsSyncPoint() fn.

IsSyncPoint() fn returns S_OK if it is a KeyFrame.

otherwise it returns S_FALSE;


In Directshow, The technical name for the KeyFrame is Synchronization Point.
So we checked it as

IsSyncPoint ()

How to identify the protected wmv/asf file?

How to identify the protected wmv/asf file ?

IWMReader ->Open( File)

if the wmv or asf file is not able to open the file,
it will returns error code as license required.
After this one, we can use the IWMDRMReader to query the license details.

Sample program available in Windows media Format SDK samples :

DRMShow.exe - i "DRMShow.wmv" // DRMShow.wmv is available in directX media dir path

HTTPStreaming Problem without KeyFrame

1. I modified the IWMWriterAdvanced:: WriteStreamSample() fn's last parameter

as 0.( It Indicates the KeyFrame).

But I didnt get any display in Windows media player, but I got like

Buffer 98% complete...After certain interval it shows status as
Buffer 96% complete...

But It doesnt Display anything in media player.


2. How to change frame rate using the Transform Filter ? Is it Possible ?

yes it is possible.

Within FillBuffer() of the Source Filter we will Set the Frame rate ..
Just refer the PushSourceDesktop Filters. There we set the frame rate dynamically.

So it is also possible to change the frame rate thru transform filter.
We need to Set the Output Media Sample's StartTime and EndTime properly to achieve the specified frame rate.

How to change frame rate using the Transform Filter ? Is it Possible ?

How to change frame rate using the Transform Filter ? Is it Possible ?

yes it is possible.

Within FillBuffer() of the Source Filter we will Set the Frame rate ..
Just refer the PushSourceDesktop Filters. There we set the frame rate dynamically.

So it is also possible to change the frame rate thru transform filter.
We need to Set the Output Media Sample's StartTime and EndTime properly to achieve the specified frame rate.


This is what I Read :
----------------------

Hi, I think you must be more precise in describing what you want to achieve. Do you actually mean : display only about half of the frames, in half of the original clip duration, resulting in fact in a 100% speed up of the clip? Or something else?

As you are using EZRGB24, there are two things you can do easily :

1) you can skip a frame by returning S_FALSE in the transform function. Add in_framecount and out_framecount as members of the Filter.

HRESULT CEZrgb24::Transform(IMediaSample *pIn, IMediaSample *pOut){

in_frameount++; // we count all incoming samples

if (somefunction of in_framecount) { return S_FALSE}; // skip if somefunction is true

out_framecount++; // here we count only actually outgoing samples

// now we process the samples

HRESULT hr = copy(pIn, pOut);

......

}

2) you can adjust the sample times by setting the pOut samples start and stop times. In fact, if you skip samples, then you must retime all samples afterwards to make sure they are correctly timestamped for display by the renderer. You should do this in the same transform function after callling the copy function. Use the out_framecount to compute the start and stop times, and set them on the pOut sample using pOut->SetTime();

Typically, you should have :

tStart = out_counter * frameduration; tStop = tStart + frameduration;

You can speed up the display by reducing frameduration.

HTTPStream Rendering problem

HTTPStream Rendering problem :
---------------------------------
I have developed the transform filter for writing the WMV
data to the HTTP Stream.It is writing data properly .

But If I render the video thru windows media player by specifying URL,
It doesnt render data properly.


But Windows media player Shows the status like


Buffer 99% complete
Playing 302Kb/s

But it doesnt render anything on the screen.



Solution :
-------------
Previously I set the KeyFrame for every 60 frames...

I used the wmvnetwrite sample application for testing.
It is sending wmv data to the HTTp stream. For any wmv file, It has OnStreamSample() callback fn
For Every frame, it will calls this function.
within this function, I checked the last parameter( KeyFrame flag), if it is true,
then I will print the Key FrameFound and the frameNumber in debug string.

I noted one thing. Key Frame is in some random order.
So I set the keyframe for every 4 frames. Now it is working.
without WM_SF_CLEANPOINT(Indicates KeyFrame), windows media player will not render data properly.
How can we identify the Key Frames within a filter ?...

Wednesday, December 12, 2007

Remote Desktop Capture using DSNetwork Sender and Receiver

1.I modified the PushSource Desktop output pin's type as
MEDIATYPE_Stream, MEDIASUBTYPE_NULL or CLSID_NULL and So on.

2.In the Code SetSockopt() fn used for making the socket connection as multicast.
network interface card address is passed as an argument to this function ( SetsockOpt()).
I commented this code in DSNetwork Sender and Receiversample application in
DXSDK.
I modified the DSNetwork and DSReceiver Filter's property pages as Simply store
what we type as IPAddress.

3.I developed the raw transform filter which accepts MEDIATYPE_Stream as input and
gives MEDIATYPE_Video and we can connect it to the renderer

I tested this filter by doing the following :

PushSourceDesktop Filter ->Raw Transform filter-> LEAD RGB converter -> Video Render


within Raw Transform filter, I hardcoded the video width as 350 and height as 288, bitcount as 16

and RGB555.


4.next Integrated the raw transform filter with DSNetwork Sender and receiver.

5. within one PC, I captured the desktop using filter

Push Source Desktop_MEDIATypeStream -> MPEG Multicast Sender

6. On another PC, I constuct the graph as follows :


MPEG Multicast Receiver -> Raw Transform Filter -> Video Renderer


Actually the MPEG multicast receiver output pin's media type is MEDIAType_Stream...



Now the captured desktop is being displayed in remote system's video Renderer.


DrawBacks :
-----------
1. It consumes more network bandwidth...
we tested it within LAN. it requires more speed...

within this method, we got the framerate as 127.
Next we have to develop the Network Sender and Network Receiver as filter with WMV format...

Monday, December 10, 2007

UDP Server and Client application

UDPServer :
--------------
1.WSAStartup()
2.socket()
3.bind()
4.recv()
5.send()



UDPClient :
------------

1.WSAStartup()
2.gethostbyaddr()
3.socket()
4.connect()
5.send()
6.receive()



UDPServer:
----------
struct sockaddr_in local, from;
WSADATA wsaData;
SOCKET listen_socket, msgsock;


WSAStartup(0x202, &wsaData)
local.sin_family = AF_INET;
local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
local.sin_port = htons(port);

listen_socket = socket(AF_INET, SOCK_DGRAM,0);

if (listen_socket == INVALID_SOCKET){ //Error}

if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR){ //error}

msgsock = listen_socket;

retval = recvfrom(msgsock,Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, &fromlen);

if(retval == SOCKET_ERROR) {return;}

//send the received data back to the client...
retval = sendto(msgsock, Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, fromlen);



UDP client :
---------------

struct sockaddr_in server;

struct hostent *hp;

WSADATA wsaData;

SOCKET conn_socket;


if (isalpha(server_name[0]))

{ // server address is a name

hp = gethostbyname(server_name);

}

else

{ // Convert nnn.nnn address to a usable one

addr = inet_addr(server_name);

hp = gethostbyaddr((char *)&addr, 4, AF_INET);

}




memset(&server, 0, sizeof(server));

memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);

server.sin_family = hp->h_addrtype;

server.sin_port = htons(port);

conn_socket = socket(AF_INET, SOCK_DGRAM, 0);

if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { //Error}


retval = send(conn_socket, Buffer, sizeof(Buffer), 0);

retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);

closesocket(conn_socket);

WSACleanup();

TCP Server and Client application

TCPServer :
-----------
struct sockaddr_in local, from;

WSADATA wsaData;

SOCKET listen_socket, msgsock;

if ((retval = WSAStartup(0x202, &wsaData)) != 0) {//Error}


local.sin_family = AF_INET;

local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);

local.sin_port = htons(port);

listen_socket = socket(AF_INET, SOCK_STREAM,0);

if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) { //Error Return}

//we can't use a UDP socket
if (listen(listen_socket,5) == SOCKET_ERROR) {//Error Return}

msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);

retval = recv(msgsock, Buffer, sizeof(Buffer), 0);

retval = send(msgsock, Buffer, sizeof(Buffer), 0);



TCP client :
-------------
struct sockaddr_in server;

struct hostent *hp;

WSADATA wsaData;

SOCKET conn_socket;

if ((retval = WSAStartup(0x202, &wsaData)) != 0) {//Error}

if (isalpha(server_name[0]))

{ // server address is a name

hp = gethostbyname(server_name);

}

else

{ // Convert nnn.nnn address to a usable one

addr = inet_addr(server_name);

hp = gethostbyaddr((char *)&addr, 4, AF_INET);

}

if(hp == NULL) { //Error return }

memset(&server, 0, sizeof(server));

memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);

server.sin_family = hp->h_addrtype;

server.sin_port = htons(port);

conn_socket = socket(AF_INET, SOCK_STREAM, 0); /* Open a socket */

if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {//Error Return}

retval = send(conn_socket, Buffer, sizeof(Buffer), 0);
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);


closesocket(conn_socket);

WSACleanup();

YUY2 to RGB24 conversion

#define FIXNUM 16
#define FIX(a, b) ((int)((a)*(1<<(b))))
#define UNFIX(a, b) ((a+(1<<(b-1)))>>(b))

// Approximate 255 by 256
#define ICCIRUV(x) (((x)<<8)/224)
#define ICCIRY(x) ((((x)-16)<<8)/219)

// Clip out-range values

#define CLIP(t) (((t)>255)?255:(((t)<0)?0:(t)))

#define GET_R_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(1.402, FIXNUM)*(v)), FIXNUM)

#define GET_G_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(-0.344, FIXNUM)*(u) + FIX(-0.714, FIXNUM)*(v)), FIXNUM)

#define GET_B_FROM_YUV(y, u, v) UNFIX((FIX(1.0, FIXNUM)*(y) + FIX(1.772, FIXNUM)*(u)), FIXNUM)

#define GET_Y_FROM_RGB(r, g, b) UNFIX((FIX(0.299, FIXNUM)*(r) + FIX(0.587, FIXNUM)*(g) + FIX(0.114, FIXNUM)*(b)), FIXNUM)

#define GET_U_FROM_RGB(r, g, b) UNFIX((FIX(-0.169, FIXNUM)*(r) + FIX(-0.331, FIXNUM)*(g) + FIX(0.500, FIXNUM)*(b)), FIXNUM)

#define GET_V_FROM_RGB(r, g, b) UNFIX((FIX(0.500, FIXNUM)*(r) + FIX(-0.419, FIXNUM)*(g) + FIX(-0.081, FIXNUM)*(b)), FIXNUM)



bool CYUVToRGB::YUV422P_to_RGB24V2(int width, int height, unsigned char *s,unsigned char *d)
{
int i;
unsigned char *p_dest;
unsigned char y1, u, y2, v;
int Y1, Y2, U, V;
unsigned char r, g, b;

p_dest = d;

int size = height * (width / 2);
unsigned long srcIndex = 0;
unsigned long dstIndex = 0;

try
{

for(i = 0 ; i < size ; i++)
{

y1 = s[srcIndex];
u = s[srcIndex+ 1];
y2 = s[srcIndex+ 2];
v = s[srcIndex+ 3];

Y1 = ICCIRY(y1);
U = ICCIRUV(u - 128);
Y2 = ICCIRY(y2);
V = ICCIRUV(v - 128);



r = CLIP(GET_R_FROM_YUV(Y1, U, V));
g = CLIP(GET_G_FROM_YUV(Y1, U, V));
b = CLIP(GET_B_FROM_YUV(Y1, U, V));


p_dest[dstIndex] = b;
p_dest[dstIndex + 1] = g;
p_dest[dstIndex + 2] = r;




dstIndex += 3;

r = CLIP(GET_R_FROM_YUV(Y2, U, V));
g = CLIP(GET_G_FROM_YUV(Y2, U, V));
b = CLIP(GET_B_FROM_YUV(Y2, U, V));

p_dest[dstIndex] = b;
p_dest[dstIndex + 1] = g;
p_dest[dstIndex + 2] = r;

dstIndex += 3;

srcIndex += 4;
}

return true;
}
catch(...)
{
OutputDebugString("\n YUV422P to RGB24V2 Failed");
return false;
}

}

Wednesday, December 05, 2007

How to use GDI+ ?

How to use GDI+ ?

For Gdi+, I added the Gdiplus.dll in C:\windows\system32 directory.
include the following lines in "stdafx.h"
#include
using namespace Gdiplus;


if the VC_EXTRALEAN or WIN32_LEAN_AND_MEAN is defined, the compiler generates
error message.

Remove these macros for using Gdi+ in VC++.
How to set output pin's media type as YUY2 ?...


we have to override the getmediaType() fn
HRESULT CRGBToYUV::GetMediaType(int iPosition, CMediaType *pMediaType)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE)
{
return E_UNEXPECTED;
}
// This should never happen
if (iPosition < 0)
{
return E_INVALIDARG;
}
// Do we have more items to offer
if (iPosition > 0) {
return VFW_S_NO_MORE_ITEMS;
}


CMediaType mt = m_pInput->CurrentMediaType();

VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*) mt.pbFormat;


VIDEOINFO *pvi = (VIDEOINFO*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
if (pvi == 0)
return(E_OUTOFMEMORY);


ZeroMemory(pvi, pMediaType->cbFormat);
//pvi->AvgTimePerFrame = m_rtFrameLength;

pvi->bmiHeader.biWidth = vih->bmiHeader.biWidth;
pvi->bmiHeader.biHeight = vih->bmiHeader.biHeight;

m_iImageWidth = vih->bmiHeader.biWidth;
m_iImageHeight = vih->bmiHeader.biHeight;

pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y','2');//MAKEFOURCC('U', 'Y', 'V', 'Y');
pvi->bmiHeader.biBitCount = 16;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
// Clear source and target rectangles
SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered
SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle

pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);

// Work out the GUID for the subtype from the header info.
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

m_pRGBBuffer = new BYTE[pvi->bmiHeader.biWidth *pvi->bmiHeader.biHeight *3];
m_pYUVBuffer = new BYTE[pvi->bmiHeader.biWidth *pvi->bmiHeader.biHeight * 2];

return NOERROR;
}

Flipped Video problem in DirectShow

Normally in Directshow we face the Flipped image problem...

if we are having image buffer, how can we flip it using code ?

This is being done by the following code...

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

Here what we have done was...

ScanLine1- 0 - Scanwidth pixels
ScanLine2 - 0 to ScanWidth Pixels
upto
ScanLineN

we have to modify it as follows for Flipping the Image Data :

ScanLine N and its pixels...
ScanLine N-1 and its Pixels

upto
ScanLine 1



For Doing this, we have developed the following code :





void FlipUpDown(BYTE* pData,int gWidth,int gHeight,int gChannels)
{
BYTE* scan0 = pData;
BYTE* scan1 = pData + ((gWidth * gHeight * gChannels) - (gWidth * gChannels));

for (unsigned int y = 0; y < gHeight / 2; y++) {
for (unsigned int x = 0; x < gWidth * gChannels; x++)
{
BYTE temp = scan0[x];
scan0[x] = scan1[x];
scan1[x] = temp;
}
scan0 += gWidth * gChannels;
scan1 -= gWidth * gChannels;
}

Custom build for Registering a Filter at Compile time

For Registering the Filter using regsvr32 During compilation,
I have done the following :
1.Open the project-> properties ->Custom build tab
and set the

Description : "Registering Directshow Filter..."
commands : regsvr32 /c "$(TargetPath)"
echo regsvr32 exec. time > "$(OutDir)\regsvr32.trg"
Outputs : $(OutDir)\regsvr32.trg

Wednesday, November 28, 2007

Calculate the execution time of a function

Calculate the execution time of a function :
we can use timeGetTime() fn available in mmsystem.h .
For using this function,
we have to include the winmm.lib


DWORD dwStartTime = timeGetTime();
StretchBlt(); // which we want to find the execution time
DWORD dwEndTime = timeGetTime();

dwEndTime - dwStartTime is the execution time.

we can also use QueryPerformanceCounter() fn to find the execution time.

Monday, November 26, 2007

While using CString in a DLL, I got an error Because it is a win32 DLL.

While using CString in a DLL, I got an error Because it is a win32 DLL.

Solution :

I modified the project ->settings->General Tab-> Use MFC in a Shared DLL or Use MFC in a Static Library...

Afterwards I included the #include in "stdafx.h" header file, now the problem is solved...

How to Avoid name mangling of a function in a DLL:

How to Avoid name mangling of a function in a DLL:

I opened my DLL using Dependency viewer in visual studio tools.

The Dependency viewer showed the functions in it as follows :

For AAPI_CleanupRecorder() fn, it displays as follows :

?AAPI_CleanupRecorder@@YGHXZ

This is called name mangling.ToSupport function overloading this will happen.
How can we disable name mangling ?...


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

we can avoid name mangling using .def file in a DLL.

I added the AAPI_CleanupRecorder() fn in a .Def file as follows :


LIBRARY AAPIPC2TV.dll

EXPORTS

AAPI_CleanupRecorder @1

I compiled the DLL and then once again opened the DLL in a "Dependency viewer".

Now the AAPI_CleanupRecorder function is available in a Dependency viewer as follows :


AAPI_CleanupRecorder

But the Demerit of this approach is we can't use the function overlaoding.

Combo Box problem in MFC dialog application

Combo Box problem in MFC dialog application :
----------------------------------------------
1.I added the combo box to the dialog and added the string to the combo box using the following code...

CComboBox* combo = (CComboBox*) GetDlgItem( IDC_COMBO1 );
combo->AddString( "one" );
combo->AddString( "two" );
combo->AddString( "three" );

If I checked the count, it returns 3 But it didnt display the text "one,two,three" on screen.


Solution:
---------
Make sure you size the combo box in the resource editor so it is big enough. Click
on the little arrow and then drag the bottom handle square down. If you are doing it in
code, make sure the rect is big enough to fit the drop-down.

I opened the .rc file in a resource editor and modified the
combo box values , Now it displays the data .The problem is combo box height is not big to display
the combo box items in a drop down or drop List

Saturday, November 24, 2007

How to change the audio capture buffer size in DirectSound's CaptureSound application ?...

How to change the audio capture buffer size in DirectSound's CaptureSound application ?...


m_dwNotifySize = 3528;
Set this Value in CreateCaptureBuffer() fn,
before this line:

m_dwNotifySize = 3528;//AudioBufferSize
m_dwCaptureBufferSize = m_dwNotifySize * NUM_REC_NOTIFICATIONS;

 

Notification buffer size is used in this application to retrive data from the Circular buffer .


we can set any size to this notification buffer size and it will be used to retrive buffer size bytes from the circular buffer.

How to change the audio capture buffer size in DirectSound's CaptureSound application ?...

How to change the audio capture buffer size in DirectSound's CaptureSound application ?...


m_dwNotifySize = 3528;
Set this Value in CreateCaptureBuffer() fn,
before this line:

m_dwNotifySize = 3528;//AudioBufferSize
m_dwCaptureBufferSize = m_dwNotifySize * NUM_REC_NOTIFICATIONS;


Notification buffer size is passed to retrieve the data from the Circular buffer.
So we can set any buffer size , this will cause the change in buffer size.

Friday, November 23, 2007

Design time combo box problem in MFC Dialog application

I got the combo box problem in VC++ 6 dialog application as follows :

1.I added the Combo box with DropList property in a dialog application
2.I added the "control" member variable from the classwizard.
3.Within OnInitDialog() fn, I added the string to the combo box.
( m_cbo.AddString("Sundar");m_cbo.AddString('Sundar");)
But the added string is not displayed at runtime.

if I set the selected index for the combo box,

m_cbo.SetCurSel(0) , the selected index string "sundar" alone displayed in a combo box at
runtime.


4. To identify the problem, I created the Dynamic combo box by code ...

and Added the string , all the strings are displayed in a combo box.

But For Design time combo box, it didnt display the text.

unsupported operation was attempted error

In an MFC Dialog based application,
I didnt have a linker error but I got an error at runtime as follows;

"An unsupported operation was attempted."

Then the application is closed...


Reason for the Error :

I have added the Combo box in a MFC dialog application and added the control variable for it.

wizard will add the code as follows : DDX_Control(pDX, IDC_cboDeviceList, m_cboDevice);

later for some reason, I deleted the combo box from the dialog.

But the following code is still in my dialog application

DDX_Control(pDX, IDC_cboDeviceList, m_cboDevice);

and causes the error "the unsupported operation was attempted"

Vista supported multimedia technologies

Windows vista supports video and audio based development technology as follows:


1.Core Audio APIs
2.Directshow
3.Microsoft Media Foundation SDK
4.Windows portable devices
5.windows Audio and Video Codec and DSP APis
6.windows media device manager11 SDk
7.Windows movie maker 6.0 and windows DVD maker 1.0 SDK
8.Windows media Format 11 SDK
9.Windows media player 11 SDK
10.windows media Rights manager 10.1.2 SDK
11.Windows media Services 9 series

Sound card capturer in Vista

Today we tested the Directsound Audio capturer in vista ...
It is not working and we checked the waveIn Multimedia APis in vista..
That is also not working.

GraphBuilder way to convert RGB to YUY2

u need the RGB to YUY2 conversion as source Filter ?

we can do RGB to YUY2 in another way also .

Build the graph with Source Filter and add the color conversion filter to it.
and render it in screen.

Note : we have to set the input and output pin of the color conversion filter as
YUY2 .

RGB to YUY2 conversion

RGB to YUY2 :
1.Convert the RGB to YUY2 in my way and store it in a file
2.Using Color space converter convert it to YUY2 and dump it in memory

Compare these two things...

Other way is to

1.Initialize DirectDraw
2.Create the RGB Surface and copy the data to RGB surface
3.Create the YUY2 Surface and copy the RGB Surface to the YUY2 Surface
4.Lock the YUY2 Surface and get the buffer data...

RGB to YUV :

RGB to YUV conversion some formulas are available...
Bytes are arranged in this manner for YUY2
For the First 3 RGB Bytes we have to find the YU
YU
For the next 3 RGB bytes, we have to find the YV.
YV
This will be continued repeatedly.
YUYVYUYV

Capturing Data from Soundcard doesn't works

Previously I got an error in capturing data from Soundcard...

Solution :
1.Right click the speaker icon appeared in the right side of the Task bar
2.The "Master Volume" titled dialog box appear.
3.Select the menu properties-> Options
4.Look at the Mixer Device...

5.There Audio and video devices are appeared...
6.Select the Audio Input device.

7.Ensure the "Checked" state of RecordingControl, MiC Volume, LineVolume and Stereo Mix of an input Device

CWaveFile Usage

void MyFunc()
{
CWaveFile* g_pWaveFile = NULL;


g_pWaveFile = new CWaveFile;
HRESULT hr = S_OK;
hr = g_pWaveFile->Open(strFileName, &wfxCaptureWaveFormat, WAVEFILE_WRITE ) ;
if(FAILED(hr)
{
OutputDebugString("Error in writing WaveFileHeader");
return;
}

DWORD dwCaptureLength;
UINT dwDataWrote;
VOID* pbCaptureData = NULL;


// Write the data into the wav file
if( FAILED( hr = g_pWaveFile->Write( dwCaptureLength,
(BYTE*)pbCaptureData,
&dwDataWrote ) ) )

return DXTRACE_ERR_MSGBOX( TEXT("Write data to wavFile"), hr );


SAFE_DELETE(g_pWaveFile);

}

CWaveFile error in Directsound

I got this error while using CWaveFile class :


SoundTest.obj : error LNK2001: unresolved external symbol "public: __thiscall CWaveFile::CWaveFile(void)" (??0CWaveFile@@$$FQAE@XZ)
SoundTest.obj : error LNK2001: unresolved external symbol "public: __thiscall CWaveFile::~CWaveFile(void)" (??1CWaveFile@@$$FQAE@XZ)


Solution :
I added the dsutil.h and dsutil.cpp in my application.
I included the library files dxerr9.lib and winmm.lib



Next I got an error like this :

Creating library QuarticsAudioCaptureDLL___Win32_Debug_unicode/AAPIPC2TV.lib and object QuarticsAudioCaptureDLL___Win32_Debug_unicode/AAPIPC2TV.exp
dsutil.obj : error LNK2001: unresolved external symbol _IID_IDirectSound3DListener
dsutil.obj : error LNK2001: unresolved external symbol _IID_IDirectSoundNotify
dsutil.obj : error LNK2001: unresolved external symbol _IID_IDirectSound3DBuffer
QuarticsAudioCaptureDLL___Win32_Debug_unicode/AAPIPC2TV.dll : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

Solution :

include the library dxguid.lib in ur application

CWaveFile available in DirectSound

class CWaveFile
{
public:
WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure
HMMIO m_hmmio; // MM I/O handle for the WAVE
MMCKINFO m_ck; // Multimedia RIFF chunk
MMCKINFO m_ckRiff; // Use in opening a WAVE file
DWORD m_dwSize; // The size of the wave file
MMIOINFO m_mmioinfoOut;
DWORD m_dwFlags;
BOOL m_bIsReadingFromMemory;
BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;

protected:
HRESULT ReadMMIO();
HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest );

public:
CWaveFile();
~CWaveFile();

HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags );
HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX* pwfx, DWORD dwFlags );
HRESULT Close();

HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead );
HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote );

DWORD GetSize();
HRESULT ResetFile();
WAVEFORMATEX* GetFormat() { return m_pwfx; };
};





//-----------------------------------------------------------------------------
// Name: CWaveFile::CWaveFile()
// Desc: Constructs the class. Call Open() to open a wave file for reading.
// Then call Read() as needed. Calling the destructor or Close()
// will close the file.
//-----------------------------------------------------------------------------
CWaveFile::CWaveFile()
{
m_pwfx = NULL;
m_hmmio = NULL;
m_pResourceBuffer = NULL;
m_dwSize = 0;
m_bIsReadingFromMemory = FALSE;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::~CWaveFile()
// Desc: Destructs the class
//-----------------------------------------------------------------------------
CWaveFile::~CWaveFile()
{
Close();

if( !m_bIsReadingFromMemory )
SAFE_DELETE_ARRAY( m_pwfx );
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::Open()
// Desc: Opens a wave file for reading
//-----------------------------------------------------------------------------
HRESULT CWaveFile::Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags )
{
HRESULT hr;

m_dwFlags = dwFlags;
m_bIsReadingFromMemory = FALSE;

if( m_dwFlags == WAVEFILE_READ )
{
if( strFileName == NULL )
return E_INVALIDARG;
SAFE_DELETE_ARRAY( m_pwfx );

m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ );

if( NULL == m_hmmio )
{
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize;
VOID* pvRes;

// Loading it as a file failed, so try it as a resource
if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAVE") ) ) )
{
if( NULL == ( hResInfo = FindResource( NULL, strFileName, TEXT("WAV") ) ) )
return DXTRACE_ERR( TEXT("FindResource"), E_FAIL );
}

if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
return DXTRACE_ERR( TEXT("LoadResource"), E_FAIL );

if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) )
return DXTRACE_ERR( TEXT("SizeofResource"), E_FAIL );

if( NULL == ( pvRes = LockResource( hResData ) ) )
return DXTRACE_ERR( TEXT("LockResource"), E_FAIL );

m_pResourceBuffer = new CHAR[ dwSize ];
memcpy( m_pResourceBuffer, pvRes, dwSize );

MMIOINFO mmioInfo;
ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer;

m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
}

if( FAILED( hr = ReadMMIO() ) )
{
// ReadMMIO will fail if its an not a wave file
mmioClose( m_hmmio, 0 );
return DXTRACE_ERR( TEXT("ReadMMIO"), hr );
}

if( FAILED( hr = ResetFile() ) )
return DXTRACE_ERR( TEXT("ResetFile"), hr );

// After the reset, the size of the wav file is m_ck.cksize so store it now
m_dwSize = m_ck.cksize;
}
else
{
m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF |
MMIO_READWRITE |
MMIO_CREATE );
if( NULL == m_hmmio )
return DXTRACE_ERR( TEXT("mmioOpen"), E_FAIL );

if( FAILED( hr = WriteMMIO( pwfx ) ) )
{
mmioClose( m_hmmio, 0 );
return DXTRACE_ERR( TEXT("WriteMMIO"), hr );
}

if( FAILED( hr = ResetFile() ) )
return DXTRACE_ERR( TEXT("ResetFile"), hr );
}

return hr;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::OpenFromMemory()
// Desc: copy data to CWaveFile member variable from memory
//-----------------------------------------------------------------------------
HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize,
WAVEFORMATEX* pwfx, DWORD dwFlags )
{
m_pwfx = pwfx;
m_ulDataSize = ulDataSize;
m_pbData = pbData;
m_pbDataCur = m_pbData;
m_bIsReadingFromMemory = TRUE;

if( dwFlags != WAVEFILE_READ )
return E_NOTIMPL;

return S_OK;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::ReadMMIO()
// Desc: Support function for reading from a multimedia I/O stream.
// m_hmmio must be valid before calling. This function uses it to
// update m_ckRiff, and m_pwfx.
//-----------------------------------------------------------------------------
HRESULT CWaveFile::ReadMMIO()
{
MMCKINFO ckIn; // chunk info. for general use.
PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in.

m_pwfx = NULL;

if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );

// Check to make sure this is a valid wave file
if( (m_ckRiff.ckid != FOURCC_RIFF) ||
(m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E') ) )
return DXTRACE_ERR( TEXT("mmioFOURCC"), E_FAIL );

// Search the input file for for the 'fmt ' chunk.
ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );

// Expect the 'fmt' chunk to be at least as large as ;
// if there are extra parameters at the end, we'll ignore them
if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) )
return DXTRACE_ERR( TEXT("sizeof(PCMWAVEFORMAT)"), E_FAIL );

// Read the 'fmt ' chunk into .
if( mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat,
sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) )
return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );

// Allocate the waveformatex, but if its not pcm format, read the next
// word, and thats how many extra bytes to allocate.
if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
{
m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ];
if( NULL == m_pwfx )
return DXTRACE_ERR( TEXT("m_pwfx"), E_FAIL );

// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = 0;
}
else
{
// Read in length of extra bytes.
WORD cbExtraBytes = 0L;
if( mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );

m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
if( NULL == m_pwfx )
return DXTRACE_ERR( TEXT("new"), E_FAIL );

// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = cbExtraBytes;

// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)),
cbExtraBytes ) != cbExtraBytes )
{
SAFE_DELETE( m_pwfx );
return DXTRACE_ERR( TEXT("mmioRead"), E_FAIL );
}
}

// Ascend the input file out of the 'fmt ' chunk.
if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) )
{
SAFE_DELETE( m_pwfx );
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );
}

return S_OK;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::GetSize()
// Desc: Retuns the size of the read access wave file
//-----------------------------------------------------------------------------
DWORD CWaveFile::GetSize()
{
return m_dwSize;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::ResetFile()
// Desc: Resets the internal m_ck pointer so reading starts from the
// beginning of the file again
//-----------------------------------------------------------------------------
HRESULT CWaveFile::ResetFile()
{
if( m_bIsReadingFromMemory )
{
m_pbDataCur = m_pbData;
}
else
{
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;

if( m_dwFlags == WAVEFILE_READ )
{
// Seek to the data
if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),
SEEK_SET ) )
return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL );

// Search the input file for the 'data' chunk.
m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
}
else
{
// Create the 'data' chunk that holds the waveform samples.
m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
m_ck.cksize = 0;

if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );

if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
}
}

return S_OK;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::Read()
// Desc: Reads section of data from a wave file into pBuffer and returns
// how much read in pdwSizeRead, reading not more than dwSizeToRead.
// This uses m_ck to determine where to start reading from. So
// subsequent calls will be continue where the last left off unless
// Reset() is called.
//-----------------------------------------------------------------------------
HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead )
{
if( m_bIsReadingFromMemory )
{
if( m_pbDataCur == NULL )
return CO_E_NOTINITIALIZED;
if( pdwSizeRead != NULL )
*pdwSizeRead = 0;

if( (BYTE*)(m_pbDataCur + dwSizeToRead) >
(BYTE*)(m_pbData + m_ulDataSize) )
{
dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData);
}

CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead );

if( pdwSizeRead != NULL )
*pdwSizeRead = dwSizeToRead;

return S_OK;
}
else
{
MMIOINFO mmioinfoIn; // current status of m_hmmio

if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( pBuffer == NULL || pdwSizeRead == NULL )
return E_INVALIDARG;

if( pdwSizeRead != NULL )
*pdwSizeRead = 0;

if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );

UINT cbDataIn = dwSizeToRead;
if( cbDataIn > m_ck.cksize )
cbDataIn = m_ck.cksize;

m_ck.cksize -= cbDataIn;

for( DWORD cT = 0; cT < cbDataIn; cT++ )
{
// Copy the bytes from the io to the buffer.
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
{
if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) )
return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );

if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"), E_FAIL );
}

// Actual copy.
*((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext);
mmioinfoIn.pchNext++;
}

if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );

if( pdwSizeRead != NULL )
*pdwSizeRead = cbDataIn;

return S_OK;
}
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::Close()
// Desc: Closes the wave file
//-----------------------------------------------------------------------------
HRESULT CWaveFile::Close()
{
if( m_dwFlags == WAVEFILE_READ )
{
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
SAFE_DELETE_ARRAY( m_pResourceBuffer );
}
else
{
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;

if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;

if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );

// Ascend the output file out of the 'data' chunk -- this will cause
// the chunk size of the 'data' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );

// Do this here instead...
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );

mmioSeek( m_hmmio, 0, SEEK_SET );

if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) )
return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );

m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');

if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
{
DWORD dwSamples = 0;
mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
mmioAscend( m_hmmio, &m_ck, 0 );
}

// Ascend the output file out of the 'RIFF' chunk -- this will cause
// the chunk size of the 'RIFF' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );

mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
}

return S_OK;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::WriteMMIO()
// Desc: Support function for reading from a multimedia I/O stream
// pwfxDest is the WAVEFORMATEX for this new wave file.
// m_hmmio must be valid before calling. This function uses it to
// update m_ckRiff, and m_ck.
//-----------------------------------------------------------------------------
HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest )
{
DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile.
MMCKINFO ckOut1;

dwFactChunk = (DWORD)-1;

// Create the output file RIFF chunk of form type 'WAVE'.
m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');
m_ckRiff.cksize = 0;

if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) )
return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );

// We are now descended into the 'RIFF' chunk we just created.
// Now create the 'fmt ' chunk. Since we know the size of this chunk,
// specify it in the MMCKINFO structure so MMIO doesn't have to seek
// back and set the chunk size after ascending from the chunk.
m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_ck.cksize = sizeof(PCMWAVEFORMAT);

if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );

// Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type.
if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM )
{
if( mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
}
else
{
// Write the variable length size.
if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(*pwfxDest) + pwfxDest->cbSize ) !=
( sizeof(*pwfxDest) + pwfxDest->cbSize ) )
return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );
}

// Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );

// Now create the fact chunk, not required for PCM but nice to have. This is filled
// in when the close routine is called.
ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
ckOut1.cksize = 0;

if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) )
return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );

if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) !=
sizeof(dwFactChunk) )
return DXTRACE_ERR( TEXT("mmioWrite"), E_FAIL );

// Now ascend out of the fact chunk...
if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) )
return DXTRACE_ERR( TEXT("mmioAscend"), E_FAIL );

return S_OK;
}




//-----------------------------------------------------------------------------
// Name: CWaveFile::Write()
// Desc: Writes data to the open wave file
//-----------------------------------------------------------------------------
HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE* pbSrcData, UINT* pnSizeWrote )
{
UINT cT;

if( m_bIsReadingFromMemory )
return E_NOTIMPL;
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( pnSizeWrote == NULL || pbSrcData == NULL )
return E_INVALIDARG;

*pnSizeWrote = 0;

for( cT = 0; cT < nSizeToWrite; cT++ )
{
if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite )
{
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) )
return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
}

*((BYTE*)m_mmioinfoOut.pchNext) = *((BYTE*)pbSrcData+cT);
(BYTE*)m_mmioinfoOut.pchNext++;

(*pnSizeWrote)++;
}

return S_OK;
}

How to call the DLL from DLL client

For DLL client application :
--------------------------------

1.we have to copy the header file from the DLL application
2.include the library path where the library file resides and copy the library and DLL fucntions
to the application path.
3.we have to include the DLL application's header file in DLL client application and
Call the Function in DLL client application before that

Deleting STL list pointers

list TestList;
list:: iterator Iter;

// Adding data to the
Iter = TestList.begin();
TestList.insert(new Test(),Iter);
Iter++;
TestList.insert(new Test(),Iter);


Test* pT = NULL;




//Removing All the pointers from the STL list as follows :


while( TestList.size() > 0)
{
Iter = TestList.begin();
pT = *Iter;
TestList.remove(pT); //Remove the item from the list
SAFE_DELETE(pT); //Free the resource
}

Thursday, November 01, 2007

C# File Access Problem

 
 I faced the problem in C# file access that is as follows :
 
 
C# file accessing Sample :
-------------------------------------


// Specify file, instructions, and privelegdes
FileStream file = new FileStream("test.txt", FileMode.Open);

// Create a new stream to read from a file
StreamReader sr = new StreamReader(file);

// Read contents of file into a string
string s = sr.ReadToEnd();

// Close StreamReader
sr.Close();

// Close file
file.Close();

  Everywhere people used the sample like this...

I also followed this sample during the development.
 I read the char by char from the streamReader object.

test.txt file is less than 1024 bytes size then the problem will not arise.

But if  file size is greater than 1024 bytes, I got the problem.


 I read the char by char from the StreamReader object.

 char[] szChar;
 szChar = new char[1];
                   strmReader.Read(szChar,0,1);

  
 After reaching the 1024 th character, I got the first character from the file...

So the StreamReader doesnt Read characters from file after 1024 characters.


Reason :

 By default StreamReader buffer size is 1024 bytes. we can also allocate the StreamReader buffer size.

if we read characters after 1024th character, StreamReader's Read() fn will returns the first character from the stream.

This will be repeated...


To avoid this problem, I allocated the StreamReader's size as File Size.
Now  we can traverse from beginning of the file to the end of the file.The code is as follows :

 

 FileStream myFile = new FileStream("test.txt",FileMode.Open);
 FileInfo fileInfo  = new FileInfo("test.txt");
 int FileLength = (int)fileInfo.Length; 
 StreamReader strmReader = new StreamReader( myFile, System.Text.Encoding.UTF8,false, FileLength);

 

 

 

 

 

 

 


 

Saturday, October 20, 2007

Dshow Companies

1.LG

2.Flextronics

3.Wipro

4.NVIDIA

5.Tata Elxsi

6.Honeywell

7.SAMSUNG

8.ARICENT

9.ST MICR0LECTRONIC

10.CADENC

11.QUALCOMM

12.L&T

13.ALCATEL
14.Sony
1.LG
 
2.Flextronics
 
3.Wipro
 
4.NVIDIA
 
5.Tata Elxsi
 
6.Honeywell
 
7.SAMSUNG
 
8.ARICENT
 
9.ST MICR0LECTRONIC
 
10.CADENC
 
11.QUALCOMM
 
12.L&T
 
13.ALCATEL
14.Sony