//========================================================================
//TITLE:
// CMedia更新至v1.4.3
//AUTHOR:
// norains
//DATE:
// Friday 27-July-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
相对v1.2.0版本进行的改进:
1.增加GetMediaProperty函数获得的属性,增加如下属性:llDuration,llAvailableEarliest,llAvailableLatest.
2.增加如下函数:SetRate(),GetRate(),GetPositionCurrent(),SetPositionCurrent() ,GetDisplayMode()
3.改进之前一些函数的HRESULT值返回BOOL值的判定方法
4.增加SetVideoWindow()一个参数,以设置可以在窗口的任意位置为起点播放视频
5.改进SetDisplayMode()函数,当窗口句柄为空时,设置播放区域为0,并返回FALSE
6.改进SetNotifyWindow()函数,令其能够接收普通的窗口消息
7.Open()的参数改为const类型,更符合实际意义
v1.2.0版本及相关用法见:http://blog.csdn.net/norains/archive/2007/05/14/1609118.aspx
我们来看看具体更新了哪些功能:
1.MEDIAPROPERTY
增加了llDuration,llAvailableEarliest,llAvailableLatest属性,分别代表影片的时间长度,最早的可拖拽的时间位置,最早的可拖拽的时间位置.这个属性可以用在GetMediaProperty()函数中.
2.SetRate(),GetRate()
SetRate()设置当前的播放速率,"1"为正常速率,"2"即为两倍速,以此类推.
GetRate()获取当前播放的速率.
3.GetPositionCurrent(),SetPositionCurrent()
GetPositionCurrent():获取当前的时间位置,返回的时间值以100ns为基本单位.
SetPositionCurrent():设置播放的时间位置,该范围必须是llAvailableEarliest和llAvailableLatest之间的数值.
4.GetDisplayMode()
该函数用来获取当前的播放模式.
v1.4.3的完整代码如下:
/////////////////////////////////////////////////////////////////////
//
//
Media.h: interface for the CMedia class.
//
//
Version:
//
1.4.3
//
Date:
//
2007.07.19
/////////////////////////////////////////////////////////////////////
/
#ifndef MEDIA_H
#define
MEDIA_H
#include
<
mmsystem.h
>
#include
<
streams.h
>
//
--------------------------------------------------------------------
//
Macro define
//
The volume value
#define
MAX_VOLUME 0
#define
MIN_VOLUME -10000
//
The balance value
#define
MAX_BALANCE 10000
#define
MIN_BALANCE -10000
//
The flag means that the area is the whole window
const
RECT RC_WHOLE_WINDOWN_AREA
=
{
0
,
0
,
0
,
0
};
//
--------------------------------------------------------------------
//
Enum value
enum
DISPLAYMODE
{
//
Fit to the play window size. How wide (height) the window is, how
//
is the move. Keep aspect ratio.
DISP_FIT,
//
Not support.Stretch to the play window size. Don't keep the aspect ratio.
DISP_STRETCH,
//
Full screen play.
DISP_FULLSCREEN,
//
When the size of video is smaller than the play window, it displayes
//
as the video size. If it's bigger , it just like the DISP_FIT mode.
DISP_NATIVE
};
//
--------------------------------------------------------------------
//
The media file property
typedef
struct
{
//
The volume range is –10,000 to 0.
//
Divide by 100 to get equivalent decibel value (for example –10,000 = –100 dB).
LONG lVolume;
//
The value from –10,000 to 10,000 indicating the stereo balance
//
As with the Volume property, units correspond to .01 decibels (multiplied by –1 when plBalance is a positive value).
//
For example, a value of 1000 indicates –10 dB on the right channel and –90 dB on the left channel.
LONG lBalance;
//
Width of the video
LONG lWidth;
//
Height of the video
LONG lHeight;
//
Approximate bit rate
LONG lBitRate;
//
The length of time that the media stream will play.
//
The duration assumes normal playback speed, and it is therefore unaffected by the rate
LONGLONG llDuration;
//
Earliest time that can be efficiently seeked to.
LONGLONG llAvailableEarliest;
//
Latest time that can be efficiently seeked to
LONGLONG llAvailableLatest;
}MEDIAPROPERTY,
*
PMEDIAPROPERTY;
//
--------------------------------------------------------------------
class
CMedia
{
public
:
DISPLAYMODE GetDisplayMode();
BOOL SetPositionCurrent(LONGLONG llPos);
BOOL GetPositionCurrent(LONGLONG
*
pllPos);
BOOL GetRate(
double
*
pdRate);
BOOL SetRate(
double
dRate);
BOOL GetEvent(LONG
*
plEvCode, LONG
*
plParam1, LONG
*
plParam2);
BOOL SetNotifyWindow(HWND hWnd, UINT wMsg,
long
lInstanceData);
BOOL SetVolume(LONG lVolume, LONG lBalance
=
0
);
BOOL SetDisplayMode(DISPLAYMODE mode);
BOOL GetMediaProperty(PMEDIAPROPERTY pOutProperty);
static
CMedia
*
GetInstance();
void
Close();
BOOL CheckVisibility();
BOOL SetVideoWindow(HWND hWndVideo,
const
RECT
&
rcDisp
=
RC_WHOLE_WINDOWN_AREA);
BOOL Open(
const
TCHAR
*
pcszFileName);
BOOL Stop();
BOOL Pause();
BOOL Play();
virtual
~
CMedia();
protected
:
CMedia();
//
Collection of interfaces
IGraphBuilder
*
m_pGB;
IMediaControl
*
m_pMC;
IMediaEventEx
*
m_pME;
IVideoWindow
*
m_pVW;
IBasicAudio
*
m_pBA;
IBasicVideo
*
m_pBV;
IMediaSeeking
*
m_pMS;
TCHAR m_szFileName[MAX_PATH];
HWND m_hWndVideo;
//
The window play video
HWND m_hWndNotify;
//
The window notify
BOOL m_bExitThrd;
BOOL m_bThrdRunning;
static
CMedia
*
m_pInstance;
DISPLAYMODE m_DispMode;
DWORD m_dwCapability;
RECT m_rcDisp;
};
#endif
//
#ifndef MEDIA_H
/////////////////////////////////////////////////////////////////////
//
//
Media.cpp: implementation of the CMedia class.
//
/////////////////////////////////////////////////////////////////////
/
#include
"
stdafx.h
"
#include
"
Media.h
"
//
========================================================================================================
//
Link the .lib
//
The lib also is copy from "(InstallDir)WINCE500PUBLICDIRECTXSDKLIB"
#pragma
comment (lib,"Ole32.lib")
#ifdef CPU_X86EM
#pragma
comment (lib,"./lib/X86em/Strmiids.lib")
#pragma
comment (lib,"./lib/X86em/Strmbase.lib")
#endif
#ifdef CPU_MIPSII
#pragma
comment (lib,"./lib/MIPSII/Strmiids.lib")
#pragma
comment (lib,"./lib/MIPSII/Strmbase.lib")
#endif
#ifdef CPU_ARM4I
#pragma
comment (lib,"./lib/ARM4I/Strmiids.lib")
#pragma
comment (lib,"./lib/ARM4I/Strmbase.lib")
#endif
//
========================================================================================================
//
----------------------------------------------------------------------------------------------
//
Macro define
//
Default play mode
#define
DEFAULT_DISPLAY_MODE DISP_NATIVE
//
----------------------------------------------------------------------
//
Initialize
CMedia
*
CMedia::m_pInstance
=
NULL;
//
------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////
/
//
Construction/Destruction
/////////////////////////////////////////////////////////////////////
/
CMedia::CMedia():
m_pGB(NULL),
m_pMC(NULL),
m_pME(NULL),
m_pVW(NULL),
m_pBA(NULL),
m_pBV(NULL),
m_pMS(NULL),
m_hWndVideo(NULL),
m_bExitThrd(TRUE),
m_bThrdRunning(FALSE),
m_DispMode(DEFAULT_DISPLAY_MODE),
m_hWndNotify(NULL),
m_rcDisp(RC_WHOLE_WINDOWN_AREA)
{
memset(m_szFileName,
0
,
sizeof
(m_szFileName));
}
CMedia::
~
CMedia()
{
if
(m_pInstance
!=
NULL)
{
delete m_pInstance;
m_pInstance
=
NULL;
}
}
//
------------------------------------------------------------
//
Description:
//
Play the media file
//
When you call the function,you should call Open() before.
//
//
-------------------------------------------------------------
BOOL CMedia::Play()
{
//
Run the graph to play the media file
if
(m_pMC
==
NULL)
{
return
FALSE;
}
return
SUCCEEDED(m_pMC
->
Run());
}
//
------------------------------------------------------------
//
Description:
//
Pause.
//
When you call the function,you should call Open() before.
//
//
-------------------------------------------------------------
BOOL CMedia::Pause()
{
if
(m_pMC
==
NULL)
{
return
FALSE;
}
return
SUCCEEDED(m_pMC
->
Pause());
}
//
------------------------------------------------------------
//
Description:
//
Stop.
//
When you call the function,you should call Open() before.
//
//
-------------------------------------------------------------
BOOL CMedia::Stop()
{
if
(m_pMC
==
NULL
||
m_pMS
==
NULL)
{
return
FALSE;
}
HRESULT hr;
hr
=
m_pMC
->
Stop();
SetPositionCurrent(
0
);
return
SUCCEEDED(hr);
}
//
--------------------------------------------------------------------------
//
Description:
//
Open the media file. When succeed in calling the function ,
//
you should call the Close() to release the resource
//
//
-------------------------------------------------------------------------
BOOL CMedia::Open(
const
TCHAR
*
pcszFileName)
{
BOOL bResult
=
FALSE;
if
(_tcslen(pcszFileName)
>=
MAX_PATH)
{
goto
END;
}
else
{
_tcscpy(m_szFileName,pcszFileName);
//
Check the file existing
HANDLE hdFile
=
CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
if
(hdFile
==
INVALID_HANDLE_VALUE)
{
//
The file doesn't exist
goto
END;
}
else
{
CloseHandle(hdFile);
}
}
//
Initialize COM
if
(CoInitializeEx(NULL, COINIT_MULTITHREADED)
!=
S_OK)
{
goto
END;
}
//
Get the interface for DirectShow's GraphBuilder
if
(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (
void
**
)
&
m_pGB)
!=
S_OK)
{
goto
END;
}
//
Have the graph construct its the appropriate graph automatically
if
(m_pGB
->
RenderFile(m_szFileName, NULL)
!=
NOERROR)
{
goto
END;
}
//
QueryInterface for DirectShow interfaces
if
(m_pGB
->
QueryInterface(IID_IMediaControl, (
void
**
)
&
m_pMC)
!=
NOERROR)
{
goto
END;
}
if
(m_pGB
->
QueryInterface(IID_IMediaEventEx, (
void
**
)
&
m_pME)
!=
NOERROR)
{
goto
END;
}
if
(m_pGB
->
QueryInterface(IID_IMediaSeeking, (
void
**
)
&
m_pMS)
!=
NOERROR)
{
goto
END;
}
//
Query for video interfaces, which may not be relevant for audio files
if
(m_pGB
->
QueryInterface(IID_IVideoWindow, (
void
**
)
&
m_pVW)
!=
NOERROR)
{
goto
END;
}
if
(m_pGB
->
QueryInterface(IID_IBasicVideo, (
void
**
)
&
m_pBV)
!=
NOERROR)
{
goto
END;
}
if
(CheckVisibility()
==
FALSE)
{
//
It just be the audio file, and don't need video filter.
//
Relinquish ownership (IMPORTANT!) after hiding
if
(m_pVW
!=
NULL)
{
m_pVW
->
put_Visible(OAFALSE);
m_pVW
->
put_Owner(NULL);
}
if
(m_pBV
!=
NULL)
{
m_pBV
->
Release();
m_pBV
=
NULL;
}
if
(m_pVW
!=
NULL)
{
m_pVW
->
Release();
m_pVW
=
NULL;
}
}
//
Query for audio interfaces, which may not be relevant for video-only files
if
(m_pGB
->
QueryInterface(IID_IBasicAudio, (
void
**
)
&
m_pBA)
!=
NOERROR)
{
goto
END;
}
//
Set play mode
SetDisplayMode(m_DispMode);
//
Get the capabilities of the media file.
m_pMS
->
GetCapabilities(
&
m_dwCapability);
bResult
=
TRUE;
END:
if
(bResult
==
FALSE)
{
//
Release the resource
Close();
}
return
bResult;
}
//
------------------------------------------------------------
//
Description:
//
This method sets an owning parent for the video window.
//
//
Parameters:
//
hWnd : [in] Handle of new owner window.
//
rcDisp: [in] The display area. If the parameter is not set,
//
it will be set as RC_WHOLE_WINDOWN_AREA which means thai
//
the whole window is for displaying the video.
//
//
----------------------------------------------------------
BOOL CMedia::SetVideoWindow(HWND hWndVideo,
const
RECT
&
rcDisp)
{
m_hWndVideo
=
hWndVideo;
m_rcDisp
=
rcDisp;
if
(m_pVW
==
NULL)
{
return
FALSE;
}
if
(FAILED(m_pVW
->
put_Owner((OAHWND)hWndVideo)))
{
return
FALSE;
}
if
(FAILED(m_pVW
->
put_WindowStyle(WS_CHILD
|
WS_CLIPSIBLINGS
|
WS_CLIPCHILDREN)))
{
return
FALSE;
}
//
Set play mode in order to notify the displayed area
return
SetDisplayMode(m_DispMode);
}
//
------------------------------------------------------------
//
Description:
//
Check the file visibility
//
When you call the function,you should call Open() before.
//
//
Parameters:
//
TRUE: Video
//
FALSE: It's not the video
//
//
------------------------------------------------------------
BOOL CMedia::CheckVisibility()
{
if
(
!
m_pVW)
{
//
No VideoWindow interface. Assuming audio/MIDI file or unsupported video codec
return
FALSE;
}
if
(
!
m_pBV)
{
//
No BasicVideo interface. Assuming audio/MIDI file or unsupported video codec.
return
FALSE;
}
//
If this is an audio-only clip, get_Visible() won't work.
//
//
Also, if this video is encoded with an unsupported codec,
//
we won't see any video, although the audio will work if it is
//
of a supported format.
long
lVisible;
return
SUCCEEDED(m_pVW
->
get_Visible(
&
lVisible));
}
//
------------------------------------------------------------
//
Description:
//
Release the resource which opened in the Open()
//
//
------------------------------------------------------------
void
CMedia::Close()
{
//
Relinquish ownership (IMPORTANT!) after hiding
if
(m_pVW
!=
NULL)
{
m_pVW
->
put_Visible(OAFALSE);
m_pVW
->
put_Owner(NULL);
}
if
(m_pMC
!=
NULL)
{
m_pMC
->
Release();
m_pMC
=
NULL;
}
if
(m_pME
!=
NULL)
{
m_pME
->
SetNotifyWindow(NULL,NULL,NULL);
m_pME
->
Release();
m_pME
=
NULL;
}
if
(m_pMS
!=
NULL)
{
m_pMS
->
Release();
m_pMS
=
NULL;
}
if
(m_pBV
!=
NULL)
{
m_pBV
->
Release();
m_pBV
=
NULL;
}
if
(m_pBA
!=
NULL)
{
m_pBA
->
Release();
m_pBA
=
NULL;
}
if
(m_pVW
!=
NULL)
{
m_pVW
->
Release();
m_pVW
=
NULL;
}
if
(m_pGB
!=
NULL)
{
m_pGB
->
Release();
m_pGB
=
NULL;
}
//
Finished with COM
memset(m_szFileName,
0
,
sizeof
(m_szFileName));
CoUninitialize();
}
//
------------------------------------------------------------
//
Description:
//
Get the instance of object
//
//
------------------------------------------------------------
CMedia
*
CMedia::GetInstance()
{
if
(m_pInstance
==
NULL)
{
m_pInstance
=
new
CMedia();
}
return
m_pInstance;
}
//
------------------------------------------------------------
//
Description:
//
Get the media file property.
//
When you call the function,you should call Open() before.
//
//
------------------------------------------------------------
BOOL CMedia::GetMediaProperty(PMEDIAPROPERTY pOutProperty)
{
MEDIAPROPERTY prop
=
{
0
};
if
(m_pBA
==
NULL
&&
m_pBV
==
NULL
&&
m_pMS
==
NULL)
{
return
FALSE;
}
//
Get the audio property
if
(m_pBA
!=
NULL)
{
m_pBA
->
get_Volume(
&
prop.lVolume);
m_pBA
->
get_Balance(
&
prop.lBalance);
}
//
Get the video property
if
(CheckVisibility()
==
TRUE
&&
m_pBV
!=
NULL)
{
m_pBV
->
get_BitRate(
&
prop.lBitRate);
m_pBV
->
GetVideoSize(
&
prop.lWidth,
&
prop.lHeight);
}
//
Get the seeking property
if
(m_pMS
!=
NULL)
{
m_pMS
->
GetDuration(
&
prop.llDuration);
m_pMS
->
GetAvailable(
&
prop.llAvailableEarliest,
&
prop.llAvailableLatest);
}
*
pOutProperty
=
prop;
return
TRUE;
}
//
------------------------------------------------------------
//
Description:
//
Set the display mode.
//
When you call the function,you should call SetVideoWindow() before.
//
If the parent windows (m_hWndVideo) is NULL, the display area would be set to zero.
//
//
------------------------------------------------------------
BOOL CMedia::SetDisplayMode(DISPLAYMODE mode)
{
if
(m_pVW
==
NULL)
{
return
FALSE;
}
if
(m_hWndVideo
==
NULL)
{
m_pVW
->
put_Left(
0
);
m_pVW
->
put_Top(
0
);
m_pVW
->
put_Width(
0
);
m_pVW
->
put_Height(
0
);
return
FALSE;
}
m_DispMode
=
mode;
if
(mode
==
DISP_FULLSCREEN)
{
m_pVW
->
put_FullScreenMode(OATRUE);
}
else
{
//
Restore to the normal mode
m_pVW
->
put_FullScreenMode(OAFALSE);
RECT rcWnd
=
m_rcDisp;
if
(rcWnd.left
==
RC_WHOLE_WINDOWN_AREA.left
&&
rcWnd.top
==
RC_WHOLE_WINDOWN_AREA.top
&&
rcWnd.right
==
RC_WHOLE_WINDOWN_AREA.right
&&
rcWnd.bottom
==
RC_WHOLE_WINDOWN_AREA.bottom )
{
GetClientRect(m_hWndVideo,
&
rcWnd);
}
LONG lWndWidth
=
rcWnd.right
-
rcWnd.left;
LONG lWndHeight
=
rcWnd.bottom
-
rcWnd.top;
MEDIAPROPERTY prop
=
{
0
};
GetMediaProperty(
&
prop);
if
(mode
==
DISP_FIT
||
mode
==
DISP_NATIVE)
{
LONG lDispLeft,lDispTop,lDispWidth,lDispHeight;
if
(mode
==
DISP_NATIVE
&&
lWndWidth
>=
prop.lWidth
&&
lWndHeight
>=
prop.lHeight)
{
lDispLeft
=
(lWndWidth
-
prop.lWidth)
/
2
+
rcWnd.left;
lDispTop
=
(lWndHeight
-
prop.lHeight)
/
2
+
rcWnd.top;
lDispWidth
=
prop.lWidth ;
lDispHeight
=
prop.lHeight ;
}
else
{
if
(prop.lWidth
*
lWndHeight
>
lWndWidth
*
prop.lHeight)
{
lDispWidth
=
lWndWidth;
lDispHeight
=
(LONG)((
float
)lDispWidth
/
(
float
)prop.lWidth
*
prop.lHeight);
lDispLeft
=
rcWnd.left;
lDispTop
=
(lWndHeight
-
lDispHeight)
/
2
+
rcWnd.top;
}
else
if
(prop.lWidth
*
lWndHeight
<
lWndWidth
*
prop.lHeight)
{
lDispHeight
=
lWndHeight;
lDispWidth
=
(LONG)((
float
)lDispHeight
/
(
float
)prop.lHeight
*
prop.lWidth);
lDispLeft
=
(lWndWidth
-
lDispWidth)
/
2
+
rcWnd.left;
lDispTop
=
rcWnd.top;
}
else
{
lDispWidth
=
lWndWidth;
lDispHeight
=
lWndHeight;
lDispLeft
=
rcWnd.left;
lDispTop
=
rcWnd.top;
}
}
m_pVW
->
put_Left(lDispLeft);
m_pVW
->
put_Top(lDispTop);
m_pVW
->
put_Width(lDispWidth);
m_pVW
->
put_Height(lDispHeight);
}
else
if
(mode
==
DISP_STRETCH)
{
m_pVW
->
put_Left(rcWnd.left);
m_pVW
->
put_Top(rcWnd.top);
m_pVW
->
put_Width(lWndWidth);
m_pVW
->
put_Height(lWndHeight);
}
}
return
TRUE;
}
//
------------------------------------------------------------
//
Description:
//
Set the volume.
//
When you call the function,you should call Open() before.
//
//
Parameters:
//
lVolume:[in] The volume (amplitude) of the audio signal.
//
Range is –10,000 to 0.
//
lBalance:[in] The balance for the audio signal. Default value is 0.
//
The value from –10,000 to 10,000 indicating the stereo balance.
//
//
------------------------------------------------------------
BOOL CMedia::SetVolume(LONG lVolume, LONG lBalance)
{
if
(m_pBA
==
NULL)
{
return
FALSE;
}
if
(lVolume
<
MIN_VOLUME
&&
lVolume
>
MAX_VOLUME
&&
lBalance
<
MIN_BALANCE
&&
lBalance
>
MAX_BALANCE)
{
return
FALSE;
}
m_pBA
->
put_Volume(lVolume);
m_pBA
->
put_Balance(lBalance);
return
TRUE;
}
//
----------------------------------------------------------------------
//
Description:
//
Registers a window that will handle the notified message when a specified event occurs and some window message
//
//
Parameters:
//
hWnd:[in] Handle of window to notify. Pass NULL to stop notification.
//
wMsg:[in] Window message to be passed as the notification.
//
lInstanceData:[in] Value (instance data) to be passed as the lParam parameter for the lMsg message.
//
//
Remarks:
//
When the notified window receive the wMsg as the notification, you could get the event code.
//
The follow codes show that process:
//
//
//
"WM_GRAPHNOTIFY" is the user-define notified message
//
case WM_GRAPHNOTIFY:
//
{
//
LONG evCode,evParam1,evParam2;
//
//
//
"m_pMedia" is the instance of the CMedia
//
if(m_pMedia->GetEvent(&evCode,&evParam1,&evParam2) == TRUE)
//
{
//
//
Check the event code
//
if(evCode == EC_COMPLETE)
//
{
//
//
Do something
//
}
//
}
//
return 0;
//
}
//
//
The event code is as follow:
//
EC_ACTIVATE An audio or video renderer is losing or gaining activation.
//
EC_BUFFERING_DATA The buffering status is changing.
//
EC_CLOCK_CHANGED The filter graph has changed from one reference clock to another.
//
EC_COMPLETE All data has been rendered.
//
EC_DRM_LEVEL Notifies when content protected by digital rights management (DRM) requests some form of analog content protection.
//
EC_END_OF_SEGMENT Notifies that a segment end has been reached.
//
EC_ERROR_STILLPLAYING At least one call to Run failed in an active filter graph.
//
The current state of any underlying filter graph or graphs is indeterminate; they might be running, but some are almost certainly not.
//
EC_ERRORABORT An error forced the termination of a requested operation.
//
EC_FULLSCREEN_LOST The video renderer is switching out of full-screen mode.
//
EC_NEED_RESTART The current graph must be stopped and restarted.
//
EC_NOTIFY_WINDOW Pass the window handle around during pin connection.
//
EC_OLE_EVENT A filter is passing a text string to the application.
//
EC_OPENING_FILE The open file status is changing.
//
EC_PALETTE_CHANGED The video palette has changed.
//
EC_QUALITY_CHANGE The playback quality has changed.
//
EC_REPAINT A repaint is required.
//
EC_SEGMENT_STARTED Notifies that a new segment has been started.
//
EC_SHUTTING_DOWN The filter graph is starting to shut down.
//
DirectShow passes this notification to any plug-in distributors that support the IMediaEventSink interface.
//
EC_STARVATION One of the filters (usually a parser or file source filter) is not receiving enough data.
//
By default, the filter graph manager will pause all running filters and then return to normal operation when enough data is available.
//
EC_STREAM_CONTROL_STARTED The starting reference time from an earlier call to IAMStreamControl::StartAt passed.
//
EC_STREAM_CONTROL_STOPPED The stopping reference time from an earlier call to IAMStreamControl::StopAt passed.
//
EC_STREAM_ERROR_STILLPLAYING The stream is still playing, but should not be playing.
//
EC_STREAM_ERROR_STOPPED The stream has stopped, but should not have stopped.
//
EC_TIME The requested reference time occurred.
//
EC_USERABORT A user has forced the termination of a requested operation.
//
EC_VIDEO_SIZE_AR_CHANGED The size or aspect ratio of the native video has changed.
//
EC_VIDEO_SIZE_CHANGED The size of the native video has changed.
//
EC_WINDOW_DESTROYED The video renderer's filter is being removed or destroyed.
//
//
//
//
DirectShow passes the following messages to the window specified by the hWnd parameter,
//
if and when the application generates them:
//
WM_KEYDOWN
//
WM_KEYUP
//
WM_LBUTTONDBLCLK
//
WM_LBUTTONDOWN
//
WM_LBUTTONUP
//
WM_MBUTTONDBLCLK
//
WM_MBUTTONDOWN
//
WM_MBUTTONUP
//
WM_MOUSEACTIVATE
//
WM_MOUSEMOVE
//
WM_RBUTTONDBLCLK
//
WM_RBUTTONDOWN
//
WM_RBUTTONUP
//
-----------------------------------------------------------------------------
BOOL CMedia::SetNotifyWindow(HWND hWnd, UINT wMsg,
long
lInstanceData)
{
if
(m_pME
==
NULL)
{
return
FALSE;
}
HRESULT hr;
hr
=
m_pME
->
SetNotifyWindow((OAHWND)hWnd,wMsg,lInstanceData);
if
(FAILED(hr))
{
return
FALSE;
}
if
(CheckVisibility()
==
TRUE
&&
m_pVW
!=
NULL)
{
hr
=
m_pVW
->
put_MessageDrain((OAHWND)hWnd);
}
return
SUCCEEDED(hr);
}
//
----------------------------------------------------------------------
//
Description:
//
This method retrieves the notification event.
//
//
-----------------------------------------------------------------------
BOOL CMedia::GetEvent(LONG
*
plEvCode, LONG
*
plParam1, LONG
*
plParam2)
{
if
(m_pME
==
NULL)
{
return
FALSE;
}
LONG evCode, evParam1, evParam2;
if
(SUCCEEDED(m_pME
->
GetEvent(
&
evCode,
&
evParam1,
&
evParam2,
0
))
==
TRUE)
{
*
plEvCode
=
evCode;
*
plParam1
=
evParam1;
*
plParam2
=
evParam2;
//
Spin through the events
m_pME
->
FreeEventParams(evCode, evParam1, evParam2);
}
else
{
return
FALSE;
}
return
TRUE;
}
//
----------------------------------------------------------------------
//
Description:
//
This method sets a new playback rate.
//
//
Parameters
//
dRate:[in] New rate, where 1 is the normal rate, 2 is twice as fast, and so on.
//
-----------------------------------------------------------------------
BOOL CMedia::SetRate(
double
dRate)
{
if
(m_pMS
==
NULL)
{
return
FALSE;
}
return
SUCCEEDED(m_pMS
->
SetRate(dRate));
}
//
----------------------------------------------------------------------
//
Description:
//
This method retrieves the current rate.
//
//
Parameters:
//
pdRate:[out] The rate
//
-----------------------------------------------------------------------
BOOL CMedia::GetRate(
double
*
pdRate)
{
if
(m_pMS
==
NULL)
{
return
FALSE;
}
return
SUCCEEDED(m_pMS
->
GetRate(pdRate));
}
//
----------------------------------------------------------------------
//
Description:
//
This method retrieves the current position in terms of the total length of the media stream
//
//
Parameters:
//
pllPos:[out]Current position.
//
-----------------------------------------------------------------------
BOOL CMedia::GetPositionCurrent(LONGLONG
*
pllPos)
{
if
(m_pMS
==
NULL)
{
return
FALSE;
}
if
(m_dwCapability
&
AM_SEEKING_CanGetCurrentPos
==
0
)
{
return
FALSE;
}
return
SUCCEEDED(m_pMS
->
GetCurrentPosition(pllPos));
}
//
----------------------------------------------------------------------
//
Description:
//
This method sets current positions
//
//
Parameters:
//
llPos:[in]Start position if stopped, or position from which to continue if paused.
//
-----------------------------------------------------------------------
BOOL CMedia::SetPositionCurrent(LONGLONG llPos)
{
if
(m_pMS
==
NULL)
{
return
FALSE;
}
LONGLONG llCur
=
0
;
if
(GetPositionCurrent(
&
llCur)
==
TRUE)
{
if
((llCur
>
llPos)
&&
(m_dwCapability
&
AM_SEEKING_CanSeekBackwards
==
0
))
{
return
FALSE;
}
else
if
((llCur
<
llPos)
&&
(m_dwCapability
&
AM_SEEKING_CanSeekForwards
==
0
))
{
return
FALSE;
}
else
if
(llCur
==
llPos)
{
//
It's the current positon, needn't set
return
TRUE;
}
}
else
if
((m_dwCapability
&
AM_SEEKING_CanSeekBackwards
==
0
)
||
(m_dwCapability
&
AM_SEEKING_CanSeekForwards
==
0
))
{
return
FALSE;
}
return
SUCCEEDED(m_pMS
->
SetPositions(
&
llPos,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning));
}
//
----------------------------------------------------------------------
//
Description:
//
This method get current display mode
//
//
----------------------------------------------------------------------
DISPLAYMODE CMedia::GetDisplayMode()
{
return
m_DispMode;
}