You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2124 lines
61 KiB
2124 lines
61 KiB
|
|
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mp2prop.cpp
|
|
|
|
Abstract:
|
|
|
|
This module contains the property page implementations.
|
|
|
|
Author:
|
|
|
|
Matthijs Gates (mgates)
|
|
|
|
Revision History:
|
|
|
|
06-Jul-1999 created
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include <streams.h>
|
|
#include <commctrl.h> // for the property pages
|
|
#include <tchar.h>
|
|
#include <mmreg.h>
|
|
#include <limits.h>
|
|
#include <bdaiface.h>
|
|
#include <ks.h> // for ksmedia.h
|
|
#include <ksmedia.h> // for bdamedia.h
|
|
#include <bdamedia.h> // for KSDATAFORMAT_TYPE_MPEG2_SECTIONS
|
|
#include "mp2res.h"
|
|
#include <initguid.h>
|
|
#include "mp2prop.h"
|
|
#include "uictrl.h"
|
|
|
|
// XXXX
|
|
// for swprintf () call ..
|
|
#include <stdio.h>
|
|
|
|
#define GOTO_NE(v,c,l) if ((v) != (c)) { goto l ; }
|
|
#define RELEASE_AND_CLEAR(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// define various contents of controls that appear in the properties
|
|
// ---------------------------------------------------------------------------
|
|
|
|
static TCHAR g_szPID [] = __TEXT("PID") ;
|
|
static TCHAR g_szStreamId [] = __TEXT("stream_id") ;
|
|
|
|
#define DISTINCT_PID_COUNT (1 << 13)
|
|
#define MAX_PID_VALUE (DISTINCT_PID_COUNT - 1)
|
|
#define STREAM_ID_MIN 0xBA
|
|
#define STREAM_ID_MAX 0xFF
|
|
|
|
//static GUID g_MediaTypeMpeg2Sections = KSDATAFORMAT_TYPE_MPEG2_SECTIONS ;
|
|
|
|
typedef
|
|
struct {
|
|
WCHAR * szTitle ;
|
|
DWORD dwWidth ;
|
|
} COL_DETAIL ;
|
|
|
|
#define LV_COL(title, width) { L#title, (width) }
|
|
|
|
// output pin listview for output pin & PID map property defined here
|
|
|
|
static
|
|
enum {
|
|
PIN_COL_PIN,
|
|
PIN_COL_COUNT
|
|
} ;
|
|
|
|
static
|
|
COL_DETAIL
|
|
g_OutputPinColumns [] = {
|
|
LV_COL (Pin, 70),
|
|
} ;
|
|
|
|
// ============================================================================
|
|
// PID map enum listview for PID map property listview control defined here
|
|
|
|
static
|
|
enum {
|
|
PID_COL_PID,
|
|
PIN_COL_PID,
|
|
MEDIA_SAMPLE_CONTENT_PID,
|
|
PID_PIN_COL_COUNT // always last
|
|
} ;
|
|
|
|
static
|
|
COL_DETAIL
|
|
g_PIDMapColumns [] = {
|
|
LV_COL (PID, 50),
|
|
LV_COL (Pin, 60),
|
|
LV_COL (Content, 180),
|
|
} ;
|
|
// ============================================================================
|
|
|
|
|
|
// ============================================================================
|
|
// PID map enum listview for PID map property listview control defined here
|
|
|
|
static
|
|
enum {
|
|
STREAM_ID_COL_STREAM,
|
|
PIN_COL_STREAM,
|
|
MEDIA_SAMPLE_CONTENT_STREAM,
|
|
FILTER_COL_STREAM,
|
|
OFFSET_COL_STREAM,
|
|
STREAM_ID_PIN_COL_COUNT // always last
|
|
} ;
|
|
|
|
static
|
|
COL_DETAIL
|
|
g_StreamIdMapColumns [] = {
|
|
LV_COL (stream_id, 60),
|
|
LV_COL (Pin, 40),
|
|
LV_COL (Content, 130),
|
|
LV_COL (Filter, 40),
|
|
LV_COL (Offset, 40),
|
|
} ;
|
|
// ============================================================================
|
|
|
|
// MEDIA_SAMPLE_CONTENT ids and descriptions
|
|
typedef
|
|
struct {
|
|
LPWSTR pszDescription ;
|
|
DWORD MediaSampleContent ;
|
|
} MEDIA_SAMPLE_CONTENT_DESC ;
|
|
|
|
// !! NOTE !! MediaSampleContent value (cast to an int) is used as an index, so
|
|
// keep the order
|
|
static
|
|
MEDIA_SAMPLE_CONTENT_DESC
|
|
g_TransportMediaSampleContentDesc [] = {
|
|
{
|
|
L"Transport Packet (complete)",
|
|
(DWORD) MEDIA_TRANSPORT_PACKET
|
|
},
|
|
{
|
|
L"Elementary Stream (A/V only)",
|
|
(DWORD) MEDIA_ELEMENTARY_STREAM
|
|
},
|
|
{
|
|
L"MPEG2 PSI Sections",
|
|
(DWORD) MEDIA_MPEG2_PSI
|
|
},
|
|
{
|
|
L"Transport Packet Payload",
|
|
(DWORD) MEDIA_TRANSPORT_PAYLOAD
|
|
}
|
|
} ;
|
|
|
|
// !! NOTE !! MediaSampleContent value (cast to an int) is used as an index, so
|
|
// keep the order
|
|
static
|
|
MEDIA_SAMPLE_CONTENT_DESC
|
|
g_ProgramMediaSampleContentDesc [] = {
|
|
{
|
|
L"Program Stream Map",
|
|
(DWORD) MPEG2_PROGRAM_STREAM_MAP
|
|
},
|
|
{
|
|
L"Elementary Stream (A/V only)",
|
|
(DWORD) MPEG2_PROGRAM_ELEMENTARY_STREAM
|
|
},
|
|
{
|
|
L"Directory PES Packet",
|
|
(DWORD) MPEG2_PROGRAM_DIRECTORY_PES_PACKET
|
|
},
|
|
{
|
|
L"Pack Header",
|
|
(DWORD) MPEG2_PROGRAM_PACK_HEADER
|
|
},
|
|
{
|
|
L"System Header",
|
|
(DWORD) MPEG2_PROGRAM_SYSTEM_HEADER
|
|
},
|
|
{
|
|
L"PES Stream",
|
|
(DWORD) MPEG2_PROGRAM_PES_STREAM
|
|
}
|
|
} ;
|
|
|
|
// format blocks for the canned types
|
|
|
|
// ac-3
|
|
static
|
|
WAVEFORMATEX
|
|
g_AC3WaveFormatEx = {
|
|
WAVE_FORMAT_UNKNOWN, // wFormatTag
|
|
2, // nChannels
|
|
48000, // nSamplesPerSec (others: 96000)
|
|
0, // nAvgBytesPerSec
|
|
0, // nBlockAlign
|
|
16, // wBitsPerSample (others: 20, 24, 0)
|
|
0 // cbSize
|
|
} ;
|
|
|
|
// WaveFormatEx format block; generated with the following settings:
|
|
//
|
|
// fwHeadFlags = 0x1c;
|
|
// wHeadEmphasis = 1;
|
|
// fwHeadModeExt = 1;
|
|
// fwHeadMode = 1;
|
|
// dwHeadBitrate = 0x3e800;
|
|
// fwHeadLayer = 0x2;
|
|
// wfx.cbSize = 0x16;
|
|
// wfx.wBitsPerSample = 0;
|
|
// wfx.nBlockAlign = 0x300;
|
|
// wfx.nAvgBytesPerSec = 0x7d00;
|
|
// wfx.nSamplesPerSec = 0xbb80;
|
|
// wfx.nChannels = 2;
|
|
// wfx.wFormatTag = 0x50;
|
|
// dwPTSLow = 0;
|
|
// dwPTSHigh = 0;
|
|
static
|
|
BYTE
|
|
g_MPEG1AudioFormat [] = {
|
|
0x50, 0x00, 0x02, 0x00, 0x80, 0xBB, 0x00, 0x00,
|
|
0x00, 0x7D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
|
|
0x16, 0x00, 0x02, 0x00, 0x00, 0xE8, 0x03, 0x00,
|
|
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1C, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
} ;
|
|
|
|
static
|
|
BYTE
|
|
g_Mpeg2ProgramVideo [] = {
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcSource.left = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcSource.top = 0x00000000
|
|
0xD0, 0x02, 0x00, 0x00, // .hdr.rcSource.right = 0x000002d0
|
|
0xE0, 0x01, 0x00, 0x00, // .hdr.rcSource.bottom = 0x000001e0
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.left = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.top = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.right = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.bottom = 0x00000000
|
|
0x00, 0x09, 0x3D, 0x00, // .hdr.dwBitRate = 0x003d0900
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwBitErrorRate = 0x00000000
|
|
0x63, 0x17, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, // .hdr.AvgTimePerFrame = 0x0000000000051763
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwInterlaceFlags = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwCopyProtectFlags = 0x00000000
|
|
0x04, 0x00, 0x00, 0x00, // .hdr.dwPictAspectRatioX = 0x00000004
|
|
0x03, 0x00, 0x00, 0x00, // .hdr.dwPictAspectRatioY = 0x00000003
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwReserved1 = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwReserved2 = 0x00000000
|
|
0x28, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biSize = 0x00000028
|
|
0xD0, 0x02, 0x00, 0x00, // .hdr.bmiHeader.biWidth = 0x000002d0
|
|
0xE0, 0x01, 0x00, 0x00, // .hdr.bmiHeader.biHeight = 0x00000000
|
|
0x00, 0x00, // .hdr.bmiHeader.biPlanes = 0x0000
|
|
0x00, 0x00, // .hdr.bmiHeader.biBitCount = 0x0000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biCompression = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biSizeImage = 0x00000000
|
|
0xD0, 0x07, 0x00, 0x00, // .hdr.bmiHeader.biXPelsPerMeter = 0x000007d0
|
|
0x27, 0xCF, 0x00, 0x00, // .hdr.bmiHeader.biYPelsPerMeter = 0x0000cf27
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biClrUsed = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biClrImportant = 0x00000000
|
|
0x98, 0xF4, 0x06, 0x00, // .dwStartTimeCode = 0x0006f498
|
|
0x56, 0x00, 0x00, 0x00, // .cbSequenceHeader = 0x00000056
|
|
0x02, 0x00, 0x00, 0x00, // .dwProfile = 0x00000002
|
|
0x02, 0x00, 0x00, 0x00, // .dwLevel = 0x00000002
|
|
0x00, 0x00, 0x00, 0x00, // .Flags = 0x00000000
|
|
// .dwSequenceHeader [1]
|
|
0x00, 0x00, 0x01, 0xB3, 0x2D, 0x01, 0xE0, 0x24,
|
|
0x09, 0xC4, 0x23, 0x81, 0x10, 0x11, 0x11, 0x12,
|
|
0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14,
|
|
0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15,
|
|
0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
|
|
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
|
0x18, 0x18, 0x18, 0x19, 0x18, 0x18, 0x18, 0x19,
|
|
0x1A, 0x1A, 0x1A, 0x1A, 0x19, 0x1B, 0x1B, 0x1B,
|
|
0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E,
|
|
0x1E, 0x1F, 0x1F, 0x21, 0x00, 0x00, 0x01, 0xB5,
|
|
0x14, 0x82, 0x00, 0x01, 0x00, 0x00
|
|
} ;
|
|
|
|
static
|
|
BYTE
|
|
g_ATSCVideoFormat [] = {
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcSource.left = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcSource.top = 0x00000000
|
|
0xC0, 0x02, 0x00, 0x00, // .hdr.rcSource.right = 0x000002c0
|
|
0xE0, 0x01, 0x00, 0x00, // .hdr.rcSource.bottom = 0x000001e0
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.left = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.top = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.right = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.rcTarget.bottom = 0x00000000
|
|
0x00, 0x1B, 0xB7, 0x00, // .hdr.dwBitRate = 0x00b71b00
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwBitErrorRate = 0x00000000
|
|
0xB1, 0x8B, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // .hdr.AvgTimePerFrame = 0x0000000000028bb1
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwInterlaceFlags = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwCopyProtectFlags = 0x00000000
|
|
0x10, 0x00, 0x00, 0x00, // .hdr.dwPictAspectRatioX = 0x00000010
|
|
0x09, 0x00, 0x00, 0x00, // .hdr.dwPictAspectRatioY = 0x00000009
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwReserved1 = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.dwReserved2 = 0x00000000
|
|
0x28, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biSize = 0x00000028
|
|
0xC0, 0x02, 0x00, 0x00, // .hdr.bmiHeader.biWidth = 0x000002c0
|
|
0xE0, 0x01, 0x00, 0x00, // .hdr.bmiHeader.biHeight = 0x000001e0
|
|
0x00, 0x00, // .hdr.bmiHeader.biPlanes = 0x0000
|
|
0x00, 0x00, // .hdr.bmiHeader.biBitCount = 0x0000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biCompression = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biSizeImage = 0x00000000
|
|
0xD0, 0x07, 0x00, 0x00, // .hdr.bmiHeader.biXPelsPerMeter = 0x000007d0
|
|
0x42, 0xD8, 0x00, 0x00, // .hdr.bmiHeader.biYPelsPerMeter = 0x0000d842
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biClrUsed = 0x00000000
|
|
0x00, 0x00, 0x00, 0x00, // .hdr.bmiHeader.biClrImportant = 0x00000000
|
|
0xC0, 0x27, 0xC8, 0x00, // .dwStartTimeCode = 0x00c827c0
|
|
0x4C, 0x00, 0x00, 0x00, // .cbSequenceHeader = 0x0000004c
|
|
0xFF, 0xFF, 0xFF, 0xFF, // .dwProfile = 0xffffffff
|
|
0xFF, 0xFF, 0xFF, 0xFF, // .dwLevel = 0xffffffff
|
|
0x00, 0x00, 0x00, 0x00, // .Flags = 0x00000000
|
|
// .dwSequenceHeader [1]
|
|
0x00, 0x00, 0x01, 0xB3, 0x2C, 0x01, 0xE0, 0x37,
|
|
0x1D, 0x4C, 0x23, 0x81, 0x10, 0x11, 0x11, 0x12,
|
|
0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14,
|
|
0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15,
|
|
0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
|
|
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
|
0x18, 0x18, 0x18, 0x19, 0x18, 0x18, 0x18, 0x19,
|
|
0x1A, 0x1A, 0x1A, 0x1A, 0x19, 0x1B, 0x1B, 0x1B,
|
|
0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1E,
|
|
0x1E, 0x1F, 0x1F, 0x21, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00
|
|
} ;
|
|
|
|
// canned types we support via the property page
|
|
|
|
// order is important ! Keep these in the same order as the
|
|
// detail declarations in g_CannedType.
|
|
static
|
|
enum {
|
|
PIN_TYPE_ATSC_VIDEO,
|
|
PIN_TYPE_MPEG2_PROGRAM_VIDEO,
|
|
PIN_TYPE_MPEG1_AUDIO,
|
|
PIN_TYPE_MPEG2_AUDIO,
|
|
PIN_TYPE_ATSC_AUDIO,
|
|
PIN_TYPE_DATA,
|
|
PIN_TYPE_TRANSPORT_STREAM,
|
|
PIN_TYPE_MPE,
|
|
PIN_TYPE_MPEG2_PSI,
|
|
NUM_CANNED_TYPE // always last
|
|
} ;
|
|
|
|
// keep these in the same order as the enum'd types above
|
|
static
|
|
struct {
|
|
WCHAR * szDescription ;
|
|
|
|
struct {
|
|
const GUID * pMajorType ;
|
|
const GUID * pSubType ;
|
|
BOOL bFixedSizeSamples ;
|
|
const GUID * pFormatType ;
|
|
int cbFormat ;
|
|
BYTE * pbFormat ;
|
|
} MediaType ;
|
|
|
|
} g_CannedType [] = {
|
|
|
|
// PIN_TYPE_ATSC_VIDEO
|
|
{
|
|
L"ATSC Video",
|
|
{
|
|
& MEDIATYPE_Video, // majortype
|
|
& MEDIASUBTYPE_MPEG2_VIDEO, // subtype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_MPEG2Video, // formattype
|
|
sizeof g_ATSCVideoFormat, // cbFormat
|
|
g_ATSCVideoFormat // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_MPEG2_PROGRAM_VIDEO
|
|
{
|
|
L"MPEG2 Program Video",
|
|
{
|
|
& MEDIATYPE_Video, // majortype
|
|
& MEDIASUBTYPE_MPEG2_VIDEO, // subtype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_MPEG2Video, // formattype
|
|
sizeof g_Mpeg2ProgramVideo, // cbFormat
|
|
g_Mpeg2ProgramVideo // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_MPEG1_AUDIO
|
|
{
|
|
L"MPEG-1 Audio",
|
|
{
|
|
& MEDIATYPE_Audio, // majortype
|
|
& MEDIASUBTYPE_MPEG1Payload, // subtype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_WaveFormatEx, // formattype
|
|
sizeof g_MPEG1AudioFormat, // cbFormat
|
|
g_MPEG1AudioFormat // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_MPEG2_AUDIO
|
|
{
|
|
L"MPEG-2 Audio",
|
|
{
|
|
& MEDIATYPE_Audio, // majortype
|
|
& MEDIASUBTYPE_MPEG2_AUDIO, // subtype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_WaveFormatEx, // formattype
|
|
sizeof g_MPEG1AudioFormat, // cbFormat
|
|
g_MPEG1AudioFormat // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_ATSC_AUDIO
|
|
{
|
|
L"ATSC Audio (AC3)",
|
|
{
|
|
& MEDIATYPE_Audio, // majortype
|
|
& MEDIASUBTYPE_DOLBY_AC3, // subtype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_WaveFormatEx, // formattype
|
|
sizeof g_AC3WaveFormatEx, // cbFormat
|
|
(BYTE *) & g_AC3WaveFormatEx // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_DATA
|
|
{
|
|
L"Transport Payload",
|
|
{
|
|
& MEDIATYPE_NULL, // majortype
|
|
& MEDIASUBTYPE_NULL, // minortype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_None, // formattype
|
|
0, // cbFormat
|
|
NULL // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_TRANSPORT_STREAM
|
|
{
|
|
L"Transport Stream",
|
|
{
|
|
& MEDIATYPE_Stream, // majortype
|
|
& MEDIASUBTYPE_MPEG2_TRANSPORT, // minortype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_None, // formattype
|
|
0, // cbFormat
|
|
NULL // pbFormat
|
|
}
|
|
},
|
|
|
|
// PIN_TYPE_MPE
|
|
{
|
|
L"DVB MPE",
|
|
{
|
|
& KSDATAFORMAT_TYPE_MPEG2_SECTIONS, // majortype
|
|
& MEDIASUBTYPE_None, // minortype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_None, // formattype
|
|
0, // cbFormat
|
|
NULL // pbFormat
|
|
}
|
|
},
|
|
// PIN_TYPE_MPEG2_PSI
|
|
{
|
|
L"MPEG-2 PSI",
|
|
{
|
|
& KSDATAFORMAT_TYPE_MPEG2_SECTIONS, // majortype
|
|
& MEDIASUBTYPE_None, // minortype
|
|
TRUE, // bFixedSizeSamples
|
|
& FORMAT_None, // formattype
|
|
0, // cbFormat
|
|
NULL // pbFormat
|
|
}
|
|
},
|
|
} ;
|
|
|
|
// TRUE / FALSE for YES / NO
|
|
static
|
|
BOOL
|
|
MessageBoxQuestion (
|
|
IN TCHAR * title,
|
|
IN TCHAR * szfmt,
|
|
...
|
|
)
|
|
{
|
|
TCHAR achbuffer [256] ;
|
|
va_list va ;
|
|
|
|
va_start (va, szfmt) ;
|
|
wvsprintf (achbuffer, szfmt, va) ;
|
|
|
|
return MessageBox (NULL, achbuffer, title, MB_YESNO | MB_ICONQUESTION) == IDYES ;
|
|
}
|
|
|
|
// error conditions
|
|
static
|
|
void
|
|
MessageBoxError (
|
|
IN TCHAR * title,
|
|
IN TCHAR * szfmt,
|
|
...
|
|
)
|
|
{
|
|
TCHAR achbuffer [256] ;
|
|
va_list va ;
|
|
|
|
va_start (va, szfmt) ;
|
|
wvsprintf (achbuffer, szfmt, va) ;
|
|
|
|
MessageBox (NULL, achbuffer, title, MB_OK | MB_ICONEXCLAMATION) ;
|
|
}
|
|
|
|
// variable param
|
|
static
|
|
void
|
|
MessageBoxVar (
|
|
IN TCHAR * title,
|
|
IN TCHAR * szfmt,
|
|
...
|
|
)
|
|
{
|
|
TCHAR achbuffer [256] ;
|
|
va_list va ;
|
|
|
|
va_start (va, szfmt) ;
|
|
wvsprintf (achbuffer, szfmt, va) ;
|
|
|
|
MessageBox (NULL, achbuffer, title, MB_OK) ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CMPEG2PropOutputPins
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CMPEG2PropOutputPins::CMPEG2PropOutputPins (
|
|
IN TCHAR * pClassName,
|
|
IN IUnknown * pIUnknown,
|
|
IN REFCLSID rclsid,
|
|
OUT HRESULT * pHr
|
|
) : CBasePropertyPage (
|
|
pClassName,
|
|
pIUnknown,
|
|
IDD_MPG2SPLT_PROP_PINS,
|
|
IDS_MPG2SPLT_PROP_PINS_TITLE
|
|
),
|
|
m_hwnd (NULL),
|
|
m_pIMpeg2Demultiplexer (NULL)
|
|
{
|
|
(* pHr) = S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::RefreshPinList_ (
|
|
)
|
|
{
|
|
CListview OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
ULONG cFetched ;
|
|
IBaseFilter * pIBaseFilter ;
|
|
IEnumPins * pIEnumPins ;
|
|
IPin * pIPin ;
|
|
HRESULT hr ;
|
|
PIN_INFO PinInfo ;
|
|
int row ;
|
|
|
|
hr = S_OK ;
|
|
|
|
pIBaseFilter = NULL ;
|
|
pIEnumPins = NULL ;
|
|
pIPin = NULL ;
|
|
PinInfo.pFilter = NULL ;
|
|
|
|
if (m_pIMpeg2Demultiplexer) {
|
|
|
|
ASSERT (m_hwnd) ;
|
|
|
|
// obtain our pin enumeration interface
|
|
hr = m_pIMpeg2Demultiplexer -> QueryInterface (
|
|
IID_IBaseFilter,
|
|
(void **) & pIBaseFilter
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
ASSERT (pIBaseFilter) ;
|
|
hr = pIBaseFilter -> EnumPins (
|
|
& pIEnumPins
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
// clear out the existing list
|
|
hr = TearDownPinList_ () ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
ASSERT (pIEnumPins) ;
|
|
for (;;) {
|
|
hr = pIEnumPins -> Next (1, & pIPin, & cFetched) ;
|
|
|
|
if (FAILED (hr) ||
|
|
hr == S_FALSE ||
|
|
cFetched == 0) {
|
|
|
|
// yuck ! set this to the lowest common denominator
|
|
hr = hr == S_FALSE ? S_OK : hr ;
|
|
pIPin = NULL ;
|
|
|
|
break ;
|
|
}
|
|
|
|
ASSERT (pIPin) ;
|
|
|
|
ZeroMemory (& PinInfo, sizeof PinInfo) ;
|
|
|
|
// retrieve our pin information
|
|
hr = pIPin -> QueryPinInfo (
|
|
& PinInfo
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
// this assert checks that things are setup properly in the
|
|
// filter code
|
|
ASSERT (PinInfo.pFilter == pIBaseFilter) ;
|
|
|
|
// we only care about output pins
|
|
if (PinInfo.dir == PINDIR_OUTPUT) {
|
|
|
|
// populate the list view
|
|
|
|
row = OutputPins.InsertRowTextW (PinInfo.achName, 0) ;
|
|
|
|
// if we succeeded, stash off the pIPin interface pointer in
|
|
// the listview, otherwise release it
|
|
if (row != -1) {
|
|
pIPin -> AddRef () ;
|
|
OutputPins.SetData ((DWORD_PTR) pIPin, row) ;
|
|
}
|
|
}
|
|
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
}
|
|
}
|
|
|
|
cleanup :
|
|
|
|
RELEASE_AND_CLEAR (pIBaseFilter) ;
|
|
RELEASE_AND_CLEAR (pIEnumPins) ;
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::TearDownPinList_ (
|
|
)
|
|
{
|
|
CListview OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
IPin * pIPin ;
|
|
|
|
if (m_hwnd) {
|
|
// walk the list view, retrieving the IPin interface
|
|
// pointers and releasing them; we delete the rows at
|
|
// the same time, so always grab the 0th row
|
|
while (OutputPins.GetItemCount () > 0) {
|
|
|
|
pIPin = (IPin *) OutputPins.GetData (0) ;
|
|
if (pIPin) {
|
|
pIPin -> Release () ;
|
|
}
|
|
else {
|
|
// prefix bugfix
|
|
return E_FAIL ;
|
|
}
|
|
|
|
if (!OutputPins.DeleteRow (0)) {
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::PopulateComboBoxes_ (
|
|
)
|
|
{
|
|
CCombobox PinType (m_hwnd, IDC_MPG2SPLT_PIN_TYPE) ;
|
|
int row ;
|
|
int i ;
|
|
WCHAR ach [32] ;
|
|
|
|
if (m_hwnd) {
|
|
// pin types
|
|
for (i = 0; i < NUM_CANNED_TYPE; i++) {
|
|
row = PinType.AppendW (g_CannedType [i].szDescription) ;
|
|
if (row != CB_ERR) {
|
|
|
|
// i corresponds to the canned type enumeration and is used
|
|
// used later to index into the g_CannedType array to retrieve
|
|
// pin type information
|
|
PinType.SetItemData (i, row) ;
|
|
}
|
|
}
|
|
PinType.Focus (0) ;
|
|
}
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnCreatePin_ (
|
|
)
|
|
{
|
|
CCombobox PinType (m_hwnd, IDC_MPG2SPLT_PIN_TYPE) ;
|
|
CListview OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
CEditControl PinName (m_hwnd, IDC_MPG2SPLT_PIN_NAME) ;
|
|
HRESULT hr ;
|
|
AM_MEDIA_TYPE MediaType = {0} ;
|
|
int r ;
|
|
DWORD dw ;
|
|
WCHAR pszPinID [128] ; // 128 = size of achName array in PIN_INFO
|
|
DWORD_PTR iCannedType ;
|
|
DWORD_PTR dwp ;
|
|
IPin * pIPin ;
|
|
|
|
ASSERT (m_hwnd) ;
|
|
|
|
hr = E_FAIL ;
|
|
|
|
if (m_pIMpeg2Demultiplexer) {
|
|
|
|
dwp = PinType.GetCurrentItemData (& iCannedType) ;
|
|
if (dwp == CB_ERR) {
|
|
return E_FAIL ;
|
|
}
|
|
|
|
ASSERT (iCannedType < NUM_CANNED_TYPE) ;
|
|
|
|
// setup the media type
|
|
MediaType.majortype = * g_CannedType [iCannedType].MediaType.pMajorType ;
|
|
MediaType.subtype = * g_CannedType [iCannedType].MediaType.pSubType ;
|
|
MediaType.bFixedSizeSamples = g_CannedType [iCannedType].MediaType.bFixedSizeSamples ;
|
|
MediaType.formattype = * g_CannedType [iCannedType].MediaType.pFormatType ;
|
|
MediaType.cbFormat = g_CannedType [iCannedType].MediaType.cbFormat ;
|
|
MediaType.pbFormat = g_CannedType [iCannedType].MediaType.pbFormat ;
|
|
|
|
// get the pin name
|
|
PinName.GetTextW (pszPinID, 128) ;
|
|
|
|
hr = m_pIMpeg2Demultiplexer -> CreateOutputPin (
|
|
& MediaType,
|
|
pszPinID,
|
|
& pIPin
|
|
) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
ASSERT (pIPin) ;
|
|
pIPin -> Release () ;
|
|
}
|
|
else {
|
|
return hr ;
|
|
}
|
|
|
|
// finally, we update the pin list in the properties
|
|
hr = RefreshPinList_ () ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
void
|
|
CMPEG2PropOutputPins::SetDirty_ (
|
|
IN BOOL fDirty
|
|
)
|
|
{
|
|
m_bDirty = fDirty ;
|
|
|
|
if (m_pPageSite) {
|
|
m_pPageSite -> OnStatusChange (fDirty ? PROPPAGESTATUS_DIRTY : PROPPAGESTATUS_CLEAN) ;
|
|
}
|
|
|
|
}
|
|
|
|
// always called after WM_INITDIALOG so we have a valid hwnd
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnActivate (
|
|
)
|
|
{
|
|
CListview OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
HRESULT hr ;
|
|
|
|
if (m_hwnd) {
|
|
// create the columns
|
|
for (int i = 0; i < PIN_COL_COUNT; i++) {
|
|
OutputPins.InsertColumnW (
|
|
g_OutputPinColumns [i].szTitle,
|
|
g_OutputPinColumns [i].dwWidth,
|
|
i
|
|
) ;
|
|
}
|
|
|
|
|
|
hr = RefreshPinList_ () ;
|
|
if (FAILED (hr)) {
|
|
return hr ;
|
|
}
|
|
|
|
return PopulateComboBoxes_ () ;
|
|
}
|
|
|
|
return E_FAIL ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnDeactivate (
|
|
)
|
|
{
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnApplyChanges (
|
|
)
|
|
{
|
|
ASSERT (m_hwnd) ;
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnConnect (
|
|
IN IUnknown * pIUnknown
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
|
|
ASSERT (pIUnknown) ;
|
|
|
|
hr = pIUnknown -> QueryInterface (
|
|
IID_IMpeg2Demultiplexer,
|
|
(void **) & m_pIMpeg2Demultiplexer
|
|
) ;
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnDisconnect (
|
|
)
|
|
{
|
|
RELEASE_AND_CLEAR (m_pIMpeg2Demultiplexer) ;
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropOutputPins::OnDeletePin_ (
|
|
)
|
|
{
|
|
CListview Pins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
int iRow ;
|
|
WCHAR achPinName [128] ; // 128 from PIN_INFO.achName
|
|
HRESULT hr ;
|
|
|
|
iRow = Pins.GetSelectedRow () ;
|
|
if (iRow == -1) {
|
|
MessageBoxError (TEXT ("Output Pin Deletion"), TEXT ("No pin is selected.")) ;
|
|
return E_FAIL ;
|
|
}
|
|
|
|
// now the Pin name
|
|
achPinName [0] = L'\0' ;
|
|
Pins.GetRowTextW (iRow, 0, 128, achPinName) ;
|
|
|
|
ASSERT (wcslen (achPinName) > 0) ;
|
|
ASSERT (m_pIMpeg2Demultiplexer) ;
|
|
|
|
hr = m_pIMpeg2Demultiplexer -> DeleteOutputPin (achPinName) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
hr = RefreshPinList_ () ;
|
|
}
|
|
else {
|
|
MessageBoxError (TEXT (""), TEXT ("failed to delete selected output pin; hr = %08xh"), hr) ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
INT_PTR
|
|
CMPEG2PropOutputPins::OnReceiveMessage (
|
|
IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
ASSERT (m_hwnd == NULL) ;
|
|
m_hwnd = hwnd ;
|
|
return TRUE ;
|
|
}
|
|
|
|
case WM_DESTROY :
|
|
{
|
|
TearDownPinList_ () ;
|
|
m_hwnd = NULL ;
|
|
break ;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD (wParam)) {
|
|
case IDC_MPG2SPLT_CREATE_PIN :
|
|
OnCreatePin_ () ;
|
|
break ;
|
|
|
|
case IDC_MPG2SPLT_PIN_TYPE :
|
|
|
|
switch (HIWORD (wParam)) {
|
|
|
|
case CBN_SELCHANGE :
|
|
break ;
|
|
} ;
|
|
break ;
|
|
|
|
//case EN_CHANGE :
|
|
// SetDirty () ;
|
|
|
|
case IDC_MPG2SPLT_DELETE_PIN :
|
|
OnDeletePin_ () ;
|
|
break ;
|
|
} ;
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
}
|
|
return CBasePropertyPage::OnReceiveMessage (
|
|
hwnd,
|
|
uMsg,
|
|
wParam,
|
|
lParam
|
|
) ;
|
|
}
|
|
|
|
// static
|
|
CUnknown *
|
|
WINAPI
|
|
CMPEG2PropOutputPins::CreateInstance (
|
|
IN IUnknown * pIUnknown,
|
|
IN HRESULT * pHr
|
|
)
|
|
{
|
|
CMPEG2PropOutputPins * pProp ;
|
|
|
|
pProp = new CMPEG2PropOutputPins (
|
|
NAME ("CMPEG2PropOutputPins"),
|
|
pIUnknown,
|
|
CLSID_MPEG2DemuxPropOutputPins,
|
|
pHr
|
|
) ;
|
|
|
|
if (pProp == NULL) {
|
|
* pHr = E_OUTOFMEMORY ;
|
|
}
|
|
|
|
return pProp ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CMpeg2PropStreamMap
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CMpeg2PropStreamMap::CMpeg2PropStreamMap (
|
|
IN TCHAR * pClassName,
|
|
IN IUnknown * pIUnknown,
|
|
IN REFCLSID rclsid,
|
|
IN int iTitleStringResource,
|
|
OUT HRESULT * pHr
|
|
) : CBasePropertyPage (
|
|
pClassName,
|
|
pIUnknown,
|
|
IDD_MPG2SPLT_PROP_STREAM_MAP,
|
|
iTitleStringResource
|
|
),
|
|
m_hwnd (NULL),
|
|
m_pIUnknown (NULL)
|
|
{
|
|
* pHr = S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::TearDownPinList_ (
|
|
)
|
|
{
|
|
CCombobox OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
IPin * pIPin ;
|
|
|
|
if (m_hwnd) {
|
|
// walk the list view, retrieving the IPin interface
|
|
// pointers and releasing them; we delete the rows at
|
|
// the same time, so always grab the 0th row
|
|
while (OutputPins.GetItemCount () > 0) {
|
|
|
|
OutputPins.GetItemData ((DWORD_PTR *) & pIPin, 0) ;
|
|
ASSERT (pIPin) ;
|
|
pIPin -> Release () ;
|
|
|
|
if (!OutputPins.DeleteRow (0)) {
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::PopulatePinList_ (
|
|
)
|
|
{
|
|
CCombobox OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
ULONG cFetched ;
|
|
IBaseFilter * pIBaseFilter ;
|
|
IEnumPins * pIEnumPins ;
|
|
IPin * pIPin ;
|
|
HRESULT hr ;
|
|
PIN_INFO PinInfo ;
|
|
int row ;
|
|
int i ;
|
|
|
|
hr = S_OK ;
|
|
|
|
pIBaseFilter = NULL ;
|
|
pIEnumPins = NULL ;
|
|
pIPin = NULL ;
|
|
PinInfo.pFilter = NULL ;
|
|
|
|
if (m_pIUnknown) {
|
|
|
|
ASSERT (m_hwnd) ;
|
|
|
|
// obtain our pin enumeration interface
|
|
hr = m_pIUnknown -> QueryInterface (
|
|
IID_IBaseFilter,
|
|
(void **) & pIBaseFilter
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
ASSERT (pIBaseFilter) ;
|
|
hr = pIBaseFilter -> EnumPins (
|
|
& pIEnumPins
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
ASSERT (pIEnumPins) ;
|
|
for (;;) {
|
|
hr = pIEnumPins -> Next (1, & pIPin, & cFetched) ;
|
|
|
|
if (FAILED (hr) ||
|
|
hr == S_FALSE ||
|
|
cFetched == 0) {
|
|
|
|
// yuck !
|
|
hr = hr == S_FALSE ? S_OK : hr ;
|
|
pIPin = NULL ;
|
|
|
|
break ;
|
|
}
|
|
|
|
ASSERT (pIPin) ;
|
|
|
|
ZeroMemory (& PinInfo, sizeof PinInfo) ;
|
|
|
|
// retrieve our pin information
|
|
hr = pIPin -> QueryPinInfo (
|
|
& PinInfo
|
|
) ;
|
|
GOTO_NE (hr, S_OK, cleanup) ;
|
|
|
|
// this assert checks that things are setup properly in the
|
|
// filter code
|
|
ASSERT (PinInfo.pFilter == pIBaseFilter) ;
|
|
|
|
// we only care about output pins
|
|
if (PinInfo.dir == PINDIR_OUTPUT) {
|
|
|
|
// populate the combo box
|
|
row = OutputPins.AppendW (PinInfo.achName) ;
|
|
|
|
// associate the pin interface
|
|
if (row == CB_ERR) {
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
|
|
// break if there was an error
|
|
break ;
|
|
}
|
|
|
|
// store the pin's interface
|
|
i = OutputPins.SetItemData ((DWORD_PTR) pIPin, row) ;
|
|
if (i == CB_ERR) {
|
|
// delete the row (does not contain a valid tuple)
|
|
OutputPins.DeleteRow (row) ;
|
|
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
|
|
// break if there was an error
|
|
break ;
|
|
}
|
|
}
|
|
else {
|
|
// input pin is not stashed
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
}
|
|
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
}
|
|
|
|
OutputPins.Focus (0) ;
|
|
}
|
|
|
|
cleanup :
|
|
|
|
RELEASE_AND_CLEAR (pIBaseFilter) ;
|
|
RELEASE_AND_CLEAR (pIEnumPins) ;
|
|
RELEASE_AND_CLEAR (PinInfo.pFilter) ;
|
|
RELEASE_AND_CLEAR (pIPin) ;
|
|
|
|
return hr ;
|
|
}
|
|
|
|
void
|
|
CMpeg2PropStreamMap::SetDirty (
|
|
IN BOOL fDirty
|
|
)
|
|
{
|
|
m_bDirty = fDirty ;
|
|
|
|
if (m_pPageSite) {
|
|
m_pPageSite -> OnStatusChange (fDirty ? PROPPAGESTATUS_DIRTY : PROPPAGESTATUS_CLEAN) ;
|
|
}
|
|
|
|
}
|
|
|
|
// always called after WM_INITDIALOG so we have a valid hwnd
|
|
HRESULT
|
|
CMpeg2PropStreamMap::OnActivate (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CListview StreamMap (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
int iColumnCount ;
|
|
|
|
hr = E_FAIL ;
|
|
|
|
if (m_hwnd) {
|
|
|
|
iColumnCount = GetStreamMapColCount () ;
|
|
|
|
// stream map table
|
|
for (int i = 0 ; i < iColumnCount ; i++) {
|
|
StreamMap.InsertColumnW (
|
|
GetStreamMapColTitle (i),
|
|
GetStreamMapColWidth (i),
|
|
i
|
|
) ;
|
|
}
|
|
|
|
// pin list
|
|
hr = PopulatePinList_ () ;
|
|
if (FAILED (hr)) {
|
|
return hr ;
|
|
}
|
|
|
|
// possible streams list
|
|
hr = PopulateStreamList_ () ;
|
|
if (FAILED (hr)) {
|
|
return hr ;
|
|
}
|
|
|
|
// media sample content list
|
|
hr = PopulateMediaSampleContentList_ () ;
|
|
if (FAILED (hr)) {
|
|
return hr ;
|
|
}
|
|
|
|
RefreshStreamMap_ () ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::OnDeactivate (
|
|
)
|
|
/*++
|
|
don't do the opposite of ::OnActivate() here because this method
|
|
is not always called. This method is only called when the property
|
|
page is tabbed away. It's not called when the user destroys the
|
|
window. Since we refcount IPin in ::OnActivate() (when we store it
|
|
in a list), depending on this method to be called and Release'ing
|
|
those refcounts doesn't work. Instead, we tear down the pin list
|
|
and Release each pin when a WM_DESTROY message is posted to the
|
|
wndproc. This happens when the user tabs away and when the property
|
|
page is destroyed.
|
|
--*/
|
|
{
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::OnApplyChanges (
|
|
)
|
|
{
|
|
ASSERT (m_hwnd) ;
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::OnConnect (
|
|
IN IUnknown * pIUnknown
|
|
)
|
|
{
|
|
ASSERT (pIUnknown) ;
|
|
|
|
m_pIUnknown = pIUnknown ;
|
|
|
|
// our ref
|
|
m_pIUnknown -> AddRef () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::OnDisconnect (
|
|
)
|
|
{
|
|
RELEASE_AND_CLEAR (m_pIUnknown) ;
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMpeg2PropStreamMap::RefreshStreamMap_ (
|
|
)
|
|
{
|
|
CListview StreamMap (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
CCombobox OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
IPin * pIPin ;
|
|
HRESULT hr ;
|
|
DWORD dwPinCount ;
|
|
DWORD i ;
|
|
|
|
hr = S_OK ;
|
|
|
|
if (m_hwnd) {
|
|
|
|
TearDownStreamMap_ () ;
|
|
|
|
dwPinCount = OutputPins.GetItemCount () ;
|
|
for (i = 0; i < dwPinCount && SUCCEEDED (hr); i++) {
|
|
|
|
OutputPins.GetItemData ((DWORD_PTR *) & pIPin, i) ;
|
|
ASSERT (pIPin) ;
|
|
|
|
hr = AppendStreamMaps (pIPin, & StreamMap) ;
|
|
}
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
INT_PTR
|
|
CMpeg2PropStreamMap::OnReceiveMessage (
|
|
IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
ASSERT (m_hwnd == NULL) ;
|
|
m_hwnd = hwnd ;
|
|
DialogInit_ () ;
|
|
return TRUE ;
|
|
}
|
|
|
|
// see ::OnDeactivate()'s comment block
|
|
case WM_DESTROY :
|
|
{
|
|
TearDownPinList_ () ;
|
|
TearDownStreamMap_ () ;
|
|
m_hwnd = NULL ;
|
|
break ;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD (wParam)) {
|
|
case IDC_MPG2SPLT_MAP_STREAM :
|
|
OnMapStream_ () ;
|
|
break ;
|
|
|
|
case IDC_MPG2SPLT_UNMAP_STREAM :
|
|
OnUnmapStream_ () ;
|
|
break ;
|
|
} ;
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
}
|
|
return CBasePropertyPage::OnReceiveMessage (
|
|
hwnd,
|
|
uMsg,
|
|
wParam,
|
|
lParam
|
|
) ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CMPEG2PropPIDMap
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CMPEG2PropPIDMap::CMPEG2PropPIDMap (
|
|
IN TCHAR * pClassName,
|
|
IN IUnknown * pIUnknown,
|
|
IN REFCLSID rclsid,
|
|
OUT HRESULT * pHr
|
|
) : CMpeg2PropStreamMap (
|
|
pClassName,
|
|
pIUnknown,
|
|
rclsid,
|
|
IDS_MPG2SPLT_PROP_PID_MAP_TITLE,
|
|
pHr
|
|
) {}
|
|
|
|
void
|
|
CMPEG2PropPIDMap::DialogInit_ (
|
|
)
|
|
{
|
|
SetWindowText (GetDlgItem (m_hwnd, IDC_MPG2SPLT_STREAMID_NAME), g_szPID) ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::PopulateStreamList_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox PIDList (m_hwnd, IDC_MPG2SPLT_STREAMS) ;
|
|
int i ;
|
|
int row ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
// populate the PID list
|
|
for (i = 0; i <= MAX_PID_VALUE; i++) {
|
|
swprintf (achbuffer, L"0x%04x", i) ;
|
|
row = PIDList.AppendW (achbuffer) ;
|
|
if (row != CB_ERR) {
|
|
PIDList.SetItemData (i, row) ;
|
|
}
|
|
}
|
|
PIDList.Focus (0) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::TearDownStreamMap_ (
|
|
)
|
|
{
|
|
CListview PIDMap (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
int i ;
|
|
int iPIDMapCount ;
|
|
IPin * pIPin ;
|
|
|
|
iPIDMapCount = PIDMap.GetItemCount () ;
|
|
|
|
for (i = 0; i < iPIDMapCount; i++) {
|
|
pIPin = reinterpret_cast <IPin *> (PIDMap.GetData (i)) ;
|
|
ASSERT (pIPin) ;
|
|
pIPin -> Release () ;
|
|
}
|
|
|
|
PIDMap.ResetContent () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::AppendStreamMaps (
|
|
IN IPin * pIPin,
|
|
IN CListview * plv
|
|
)
|
|
{
|
|
IEnumPIDMap * pIEnumPIDMap ;
|
|
HRESULT hr ;
|
|
IMPEG2PIDMap * pIPinPIDMap ;
|
|
OLECHAR * pszPinID ;
|
|
WCHAR achbuffer [32] ;
|
|
int row ;
|
|
PID_MAP PIDMap ;
|
|
DWORD dwGot ;
|
|
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2PIDMap,
|
|
(void **) & pIPinPIDMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIPinPIDMap -> EnumPIDMap (
|
|
& pIEnumPIDMap
|
|
) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIPin -> QueryId (& pszPinID) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
|
|
for (;;) {
|
|
hr = pIEnumPIDMap -> Next (
|
|
1,
|
|
& PIDMap,
|
|
& dwGot
|
|
) ;
|
|
if (hr == S_FALSE ||
|
|
dwGot == 0) {
|
|
|
|
// not a true failure of the call
|
|
hr = S_OK ;
|
|
break ;
|
|
}
|
|
|
|
if (FAILED (hr)) {
|
|
// true failure
|
|
break ;
|
|
}
|
|
|
|
row = plv -> InsertRowValue (
|
|
reinterpret_cast <DWORD_PTR> (pIPin)
|
|
) ;
|
|
if (row == -1) {
|
|
hr = E_FAIL ;
|
|
break ;
|
|
}
|
|
|
|
// listview's ref
|
|
pIPin -> AddRef () ;
|
|
|
|
// PID
|
|
swprintf (achbuffer, L"0x%04x", PIDMap.ulPID) ;
|
|
plv -> SetTextW (
|
|
achbuffer,
|
|
row,
|
|
PID_COL_PID
|
|
) ;
|
|
|
|
// pin
|
|
plv -> SetTextW (
|
|
pszPinID,
|
|
row,
|
|
PIN_COL_PID
|
|
) ;
|
|
|
|
// PID map content
|
|
ASSERT (PIDMap.MediaSampleContent <= MEDIA_TRANSPORT_PAYLOAD) ;
|
|
plv -> SetTextW (
|
|
g_TransportMediaSampleContentDesc [PIDMap.MediaSampleContent].pszDescription,
|
|
row,
|
|
MEDIA_SAMPLE_CONTENT_PID
|
|
) ;
|
|
}
|
|
|
|
CoTaskMemFree (pszPinID) ;
|
|
}
|
|
|
|
pIEnumPIDMap -> Release () ;
|
|
}
|
|
|
|
pIPinPIDMap -> Release () ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::OnMapStream_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox PID (m_hwnd, IDC_MPG2SPLT_STREAMS) ;
|
|
CCombobox MediaContent (m_hwnd, IDC_MPG2SPLT_MEDIA_SAMPLE_CONTENT) ;
|
|
CCombobox OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
DWORD dwPID ;
|
|
WCHAR achPin [128] ; // 128 is PIN_INFO.achName length
|
|
MEDIA_SAMPLE_CONTENT MediaSampleContent ;
|
|
DWORD_PTR dwptr ;
|
|
IMPEG2PIDMap * pIMpeg2PIDMap ;
|
|
IPin * pIPin ;
|
|
|
|
// gather the data
|
|
|
|
MediaContent.GetCurrentItemData (& dwptr) ;
|
|
MediaSampleContent = (MEDIA_SAMPLE_CONTENT) dwptr ; // safe cast
|
|
|
|
PID.GetCurrentItemData (& dwptr) ;
|
|
dwPID = (DWORD) dwptr ; // safe cast
|
|
|
|
OutputPins.GetCurrentItemData (& dwptr) ;
|
|
if (dwptr == CB_ERR) {
|
|
return E_FAIL ;
|
|
}
|
|
|
|
pIPin = reinterpret_cast <IPin *> (dwptr) ;
|
|
ASSERT (pIPin) ;
|
|
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2PIDMap,
|
|
(void **) & pIMpeg2PIDMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIMpeg2PIDMap -> MapPID (
|
|
1,
|
|
& dwPID,
|
|
MediaSampleContent
|
|
) ;
|
|
|
|
pIMpeg2PIDMap -> Release () ;
|
|
}
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
RefreshStreamMap_ () ;
|
|
}
|
|
else {
|
|
MessageBoxError (TEXT("PID Map"), TEXT("Could not map PID %04x; %08xh"), dwPID, hr) ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::OnUnmapStream_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CListview PIDMaps (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
DWORD dwPID ;
|
|
int iRow ;
|
|
WCHAR achPinName [128] ; // 128 from PIN_INFO.achName
|
|
IMPEG2PIDMap * pIMpeg2PIDMap ;
|
|
IPin * pIPin ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
iRow = PIDMaps.GetSelectedRow () ;
|
|
if (iRow == -1) {
|
|
MessageBoxError (TEXT ("PID Map Deletion"), TEXT ("No PID mapping is selected.")) ;
|
|
return E_FAIL ;
|
|
}
|
|
|
|
// get the PID
|
|
achbuffer [0] = L'\0' ;
|
|
if (PIDMaps.GetRowTextW (iRow, PID_COL_PID, 32, achbuffer) > 0) {
|
|
if (swscanf (achbuffer, L"0x%04x", & dwPID) == 0) {
|
|
// PREFIX fix
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
else {
|
|
// prefix bugfix
|
|
return E_FAIL ;
|
|
}
|
|
|
|
// dwPID now contains a valid PID
|
|
|
|
// and the pin to which it is mapped
|
|
pIPin = reinterpret_cast <IPin *> (PIDMaps.GetData (iRow)) ;
|
|
ASSERT (pIPin) ;
|
|
|
|
// the interface we're going to use
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2PIDMap,
|
|
(void **) & pIMpeg2PIDMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
// unmap
|
|
hr = pIMpeg2PIDMap -> UnmapPID (
|
|
1,
|
|
& dwPID
|
|
) ;
|
|
|
|
pIMpeg2PIDMap -> Release () ;
|
|
}
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
RefreshStreamMap_ () ;
|
|
}
|
|
else {
|
|
MessageBoxError (TEXT("PID Unmap"), TEXT("Could not unmap PID %04x; %08xh"), dwPID, hr) ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
WCHAR *
|
|
CMPEG2PropPIDMap::GetStreamMapColTitle (
|
|
IN int iCol
|
|
)
|
|
{
|
|
return g_PIDMapColumns [iCol].szTitle ;
|
|
}
|
|
|
|
int
|
|
CMPEG2PropPIDMap::GetStreamMapColCount (
|
|
)
|
|
{
|
|
return PID_PIN_COL_COUNT ;
|
|
}
|
|
|
|
int
|
|
CMPEG2PropPIDMap::GetStreamMapColWidth (
|
|
IN int iCol
|
|
)
|
|
{
|
|
return g_PIDMapColumns [iCol].dwWidth ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropPIDMap::PopulateMediaSampleContentList_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox MediaSampleContent (m_hwnd, IDC_MPG2SPLT_MEDIA_SAMPLE_CONTENT) ;
|
|
int row ;
|
|
int k, i ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
// populate the media sample content choices
|
|
k = sizeof g_TransportMediaSampleContentDesc / sizeof MEDIA_SAMPLE_CONTENT_DESC ;
|
|
for (i = 0; i < k; i++) {
|
|
row = MediaSampleContent.AppendW (g_TransportMediaSampleContentDesc [i].pszDescription) ;
|
|
if (row != CB_ERR) {
|
|
MediaSampleContent.SetItemData (g_TransportMediaSampleContentDesc [i].MediaSampleContent, row) ;
|
|
}
|
|
else {
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
MediaSampleContent.Focus (0) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
// static
|
|
CUnknown *
|
|
WINAPI
|
|
CMPEG2PropPIDMap::CreateInstance (
|
|
IN IUnknown * pIUnknown,
|
|
IN HRESULT * pHr
|
|
)
|
|
{
|
|
CMpeg2PropStreamMap * pProp ;
|
|
|
|
pProp = new CMPEG2PropPIDMap (
|
|
NAME ("CMPEG2PropPIDMap"),
|
|
pIUnknown,
|
|
CLSID_MPEG2DemuxPropPIDMap,
|
|
pHr
|
|
) ;
|
|
|
|
if (pProp == NULL) {
|
|
* pHr = E_OUTOFMEMORY ;
|
|
}
|
|
|
|
return pProp ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CMPEG2PropStreamIdMap
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CMPEG2PropStreamIdMap::CMPEG2PropStreamIdMap (
|
|
IN TCHAR * pClassName,
|
|
IN IUnknown * pIUnknown,
|
|
IN REFCLSID rclsid,
|
|
OUT HRESULT * pHr
|
|
) : CMpeg2PropStreamMap (
|
|
pClassName,
|
|
pIUnknown,
|
|
rclsid,
|
|
IDS_MPG2SPLT_PROP_STREAMID_MAP_TITLE,
|
|
pHr
|
|
) {}
|
|
|
|
void
|
|
CMPEG2PropStreamIdMap::DialogInit_ (
|
|
)
|
|
{
|
|
int i, k ;
|
|
WCHAR achbuffer [32] ;
|
|
CCombobox DataOffset (m_hwnd, IDC_MPG2SPLT_DATA_OFFSET) ;
|
|
CCombobox FilterValue (m_hwnd, IDC_MPG2SPLT_FILTER_VALUE) ;
|
|
int row, rowDefault ;
|
|
|
|
SetWindowText (GetDlgItem (m_hwnd, IDC_MPG2SPLT_STREAMID_NAME), g_szStreamId) ;
|
|
|
|
ShowWindow (GetDlgItem (m_hwnd, IDC_MPG2SPLT_FILTER_VALUE), SW_SHOW) ;
|
|
ShowWindow (GetDlgItem (m_hwnd, IDC_MPG2SPLT_FILTER_VALUE_LABEL), SW_SHOW) ;
|
|
ShowWindow (GetDlgItem (m_hwnd, IDC_MPG2SPLT_DATA_OFFSET), SW_SHOW) ;
|
|
ShowWindow (GetDlgItem (m_hwnd, IDC_MPG2SPLT_DATA_OFFSET_LABEL), SW_SHOW) ;
|
|
ShowWindow (GetDlgItem (m_hwnd, IDC_MPG2SPLT_SUBSTREAM_FRAME), SW_SHOW) ;
|
|
|
|
// populate the controls as well
|
|
for (i = 0; i < 11; i++) {
|
|
swprintf (achbuffer, L"%d", i) ;
|
|
row = DataOffset.AppendW (achbuffer) ;
|
|
if (row != CB_ERR) {
|
|
DataOffset.SetItemData (i, row) ;
|
|
}
|
|
}
|
|
DataOffset.Focus (0) ;
|
|
|
|
// filter value
|
|
|
|
swprintf (achbuffer, L"none") ;
|
|
rowDefault = FilterValue.AppendW (achbuffer) ;
|
|
if (rowDefault != CB_ERR) {
|
|
FilterValue.SetItemData (SUBSTREAM_FILTER_VAL_NONE, rowDefault) ;
|
|
}
|
|
|
|
for (k = 0; k < 8; k++) {
|
|
swprintf (achbuffer, L"0x%02x", 0x80 + k) ;
|
|
row = FilterValue.AppendW (achbuffer) ;
|
|
if (row != CB_ERR) {
|
|
FilterValue.SetItemData (0x80 + k, row) ;
|
|
}
|
|
}
|
|
FilterValue.Focus (rowDefault) ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::PopulateStreamList_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox StreamIdList (m_hwnd, IDC_MPG2SPLT_STREAMS) ;
|
|
int i ;
|
|
int row ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
// populate the PID list
|
|
for (i = STREAM_ID_MIN; i <= STREAM_ID_MAX; i++) {
|
|
swprintf (achbuffer, L"0x%02X", i) ;
|
|
row = StreamIdList.AppendW (achbuffer) ;
|
|
if (row != CB_ERR) {
|
|
StreamIdList.SetItemData (i, row) ;
|
|
}
|
|
}
|
|
StreamIdList.Focus (0) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::TearDownStreamMap_ (
|
|
)
|
|
{
|
|
CListview StreamMap (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
int i ;
|
|
int iStreamMapCount ;
|
|
IPin * pIPin ;
|
|
|
|
iStreamMapCount = StreamMap.GetItemCount () ;
|
|
|
|
for (i = 0; i < iStreamMapCount; i++) {
|
|
pIPin = reinterpret_cast <IPin *> (StreamMap.GetData (i)) ;
|
|
ASSERT (pIPin) ;
|
|
pIPin -> Release () ;
|
|
}
|
|
|
|
StreamMap.ResetContent () ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::AppendStreamMaps (
|
|
IN IPin * pIPin,
|
|
IN CListview * plv
|
|
)
|
|
{
|
|
IEnumStreamIdMap * pIEnumStreamIdMap ;
|
|
HRESULT hr ;
|
|
IMPEG2StreamIdMap * pIPinStreamIdMap ;
|
|
OLECHAR * pszPinID ;
|
|
WCHAR achbuffer [32] ;
|
|
int row ;
|
|
STREAM_ID_MAP StreamIdMap ;
|
|
DWORD dwGot ;
|
|
|
|
// media sample content is used as a 0-based index, so we assume the
|
|
// first is 0
|
|
ASSERT (MPEG2_PROGRAM_STREAM_MAP == 0) ;
|
|
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2StreamIdMap,
|
|
(void **) & pIPinStreamIdMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIPinStreamIdMap -> EnumStreamIdMap (
|
|
& pIEnumStreamIdMap
|
|
) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIPin -> QueryId (& pszPinID) ;
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
|
|
for (;;) {
|
|
hr = pIEnumStreamIdMap -> Next (
|
|
1,
|
|
& StreamIdMap,
|
|
& dwGot
|
|
) ;
|
|
if (hr == S_FALSE ||
|
|
dwGot == 0) {
|
|
|
|
// not a true failure of the call
|
|
hr = S_OK ;
|
|
break ;
|
|
}
|
|
|
|
if (FAILED (hr)) {
|
|
// true failure
|
|
break ;
|
|
}
|
|
|
|
row = plv -> InsertRowValue (
|
|
reinterpret_cast <DWORD_PTR> (pIPin)
|
|
) ;
|
|
if (row == -1) {
|
|
hr = E_FAIL ;
|
|
break ;
|
|
}
|
|
|
|
// listview's ref
|
|
pIPin -> AddRef () ;
|
|
|
|
// stream_id
|
|
swprintf (achbuffer, L"0x%02X", StreamIdMap.stream_id) ;
|
|
plv -> SetTextW (
|
|
achbuffer,
|
|
row,
|
|
STREAM_ID_COL_STREAM
|
|
) ;
|
|
|
|
// pin
|
|
plv -> SetTextW (
|
|
pszPinID,
|
|
row,
|
|
PIN_COL_STREAM
|
|
) ;
|
|
|
|
// stream id map content
|
|
ASSERT (StreamIdMap.dwMediaSampleContent <= MPEG2_PROGRAM_ELEMENTARY_STREAM) ;
|
|
plv -> SetTextW (
|
|
g_ProgramMediaSampleContentDesc [StreamIdMap.dwMediaSampleContent].pszDescription,
|
|
row,
|
|
MEDIA_SAMPLE_CONTENT_STREAM
|
|
) ;
|
|
|
|
// filter
|
|
|
|
if (StreamIdMap.ulSubstreamFilterValue != SUBSTREAM_FILTER_VAL_NONE) {
|
|
swprintf (achbuffer, L"0x%02x", StreamIdMap.ulSubstreamFilterValue) ;
|
|
}
|
|
else {
|
|
swprintf (achbuffer, L"none") ;
|
|
}
|
|
|
|
plv -> SetTextW (
|
|
achbuffer,
|
|
row,
|
|
FILTER_COL_STREAM
|
|
) ;
|
|
|
|
// offset
|
|
|
|
swprintf (achbuffer, L"%d", StreamIdMap.iDataOffset) ;
|
|
plv -> SetTextW (
|
|
achbuffer,
|
|
row,
|
|
OFFSET_COL_STREAM
|
|
) ;
|
|
}
|
|
|
|
CoTaskMemFree (pszPinID) ;
|
|
}
|
|
|
|
pIEnumStreamIdMap -> Release () ;
|
|
}
|
|
|
|
pIPinStreamIdMap -> Release () ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::OnMapStream_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox StreamId (m_hwnd, IDC_MPG2SPLT_STREAMS) ;
|
|
CCombobox MediaContent (m_hwnd, IDC_MPG2SPLT_MEDIA_SAMPLE_CONTENT) ;
|
|
CCombobox OutputPins (m_hwnd, IDC_MPG2SPLT_OUTPUT_PINS) ;
|
|
CCombobox DataOffset (m_hwnd, IDC_MPG2SPLT_DATA_OFFSET) ;
|
|
CCombobox FilterValue (m_hwnd, IDC_MPG2SPLT_FILTER_VALUE) ;
|
|
DWORD dwStreamId ;
|
|
WCHAR achPin [128] ; // 128 is PIN_INFO.achName length
|
|
DWORD MediaSampleContent ;
|
|
DWORD_PTR dwptr ;
|
|
IMPEG2StreamIdMap * pIMpeg2StreamIdMap ;
|
|
IPin * pIPin ;
|
|
DWORD dwFilterVal ;
|
|
int iDataOffset ;
|
|
|
|
// gather the data
|
|
|
|
MediaContent.GetCurrentItemData (& dwptr) ;
|
|
MediaSampleContent = (DWORD) dwptr ; // safe cast
|
|
|
|
StreamId.GetCurrentItemData (& dwptr) ;
|
|
dwStreamId = (DWORD) dwptr ; // safe cast
|
|
|
|
OutputPins.GetCurrentItemData (& dwptr) ;
|
|
if (dwptr == CB_ERR) {
|
|
return E_FAIL ;
|
|
}
|
|
|
|
pIPin = reinterpret_cast <IPin *> (dwptr) ;
|
|
ASSERT (pIPin) ;
|
|
|
|
DataOffset.GetCurrentItemData (& dwptr) ;
|
|
iDataOffset = (int) dwptr ;
|
|
|
|
FilterValue.GetCurrentItemData (& dwptr) ;
|
|
dwFilterVal = (DWORD) dwptr ;
|
|
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2StreamIdMap,
|
|
(void **) & pIMpeg2StreamIdMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
hr = pIMpeg2StreamIdMap -> MapStreamId (
|
|
dwStreamId,
|
|
MediaSampleContent,
|
|
dwFilterVal,
|
|
iDataOffset
|
|
) ;
|
|
|
|
pIMpeg2StreamIdMap -> Release () ;
|
|
}
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
RefreshStreamMap_ () ;
|
|
}
|
|
else {
|
|
MessageBoxError (TEXT("StreamId Map"), TEXT("Could not map stream_id %02x; %08xh"), dwStreamId, hr) ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::OnUnmapStream_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CListview StreamMaps (m_hwnd, IDC_MPG2SPLT_STREAM_MAPPINGS) ;
|
|
DWORD dwStreamId ;
|
|
int iRow ;
|
|
WCHAR achPinName [128] ; // 128 from PIN_INFO.achName
|
|
IMPEG2StreamIdMap * pIMpeg2StreamIdMap ;
|
|
IPin * pIPin ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
iRow = StreamMaps.GetSelectedRow () ;
|
|
if (iRow == -1) {
|
|
MessageBoxError (TEXT ("Stream Map Deletion"), TEXT ("No stream mapping is selected.")) ;
|
|
return E_FAIL ;
|
|
}
|
|
|
|
// get the stream_id
|
|
achbuffer [0] = L'\0' ;
|
|
if (StreamMaps.GetRowTextW (iRow, STREAM_ID_COL_STREAM, 32, achbuffer) > 0) {
|
|
if (swscanf (achbuffer, L"0x%04x", & dwStreamId) == 0) {
|
|
// PREFIX fix
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
else {
|
|
// PREFIX fix
|
|
return E_FAIL ;
|
|
}
|
|
|
|
// dwStreamId now contains a valid value
|
|
|
|
// and the pin to which it is mapped
|
|
pIPin = reinterpret_cast <IPin *> (StreamMaps.GetData (iRow)) ;
|
|
ASSERT (pIPin) ;
|
|
|
|
// the interface we're going to use
|
|
hr = pIPin -> QueryInterface (
|
|
IID_IMPEG2StreamIdMap,
|
|
(void **) & pIMpeg2StreamIdMap
|
|
) ;
|
|
if (SUCCEEDED (hr)) {
|
|
// unmap
|
|
hr = pIMpeg2StreamIdMap -> UnmapStreamId (
|
|
1,
|
|
& dwStreamId
|
|
) ;
|
|
|
|
pIMpeg2StreamIdMap -> Release () ;
|
|
}
|
|
|
|
if (SUCCEEDED (hr)) {
|
|
RefreshStreamMap_ () ;
|
|
}
|
|
else {
|
|
MessageBoxError (TEXT("PID Unmap"), TEXT("Could not unmap stream %04x; %08xh"), dwStreamId, hr) ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
int
|
|
CMPEG2PropStreamIdMap::GetStreamMapColCount (
|
|
)
|
|
{
|
|
return STREAM_ID_PIN_COL_COUNT ;
|
|
}
|
|
|
|
|
|
WCHAR *
|
|
CMPEG2PropStreamIdMap::GetStreamMapColTitle (
|
|
IN int iCol
|
|
)
|
|
{
|
|
return g_StreamIdMapColumns [iCol].szTitle ;
|
|
}
|
|
|
|
int
|
|
CMPEG2PropStreamIdMap::GetStreamMapColWidth (
|
|
IN int iCol
|
|
)
|
|
{
|
|
return g_StreamIdMapColumns [iCol].dwWidth ;
|
|
}
|
|
|
|
HRESULT
|
|
CMPEG2PropStreamIdMap::PopulateMediaSampleContentList_ (
|
|
)
|
|
{
|
|
HRESULT hr ;
|
|
CCombobox MediaSampleContent (m_hwnd, IDC_MPG2SPLT_MEDIA_SAMPLE_CONTENT) ;
|
|
int row ;
|
|
int k, i ;
|
|
WCHAR achbuffer [32] ;
|
|
|
|
// populate the media sample content choices
|
|
k = sizeof g_ProgramMediaSampleContentDesc / sizeof MEDIA_SAMPLE_CONTENT_DESC ;
|
|
for (i = 0; i < k; i++) {
|
|
row = MediaSampleContent.AppendW (g_ProgramMediaSampleContentDesc [i].pszDescription) ;
|
|
if (row != CB_ERR) {
|
|
MediaSampleContent.SetItemData (g_ProgramMediaSampleContentDesc [i].MediaSampleContent, row) ;
|
|
}
|
|
else {
|
|
return E_FAIL ;
|
|
}
|
|
}
|
|
MediaSampleContent.Focus (0) ;
|
|
|
|
return S_OK ;
|
|
}
|
|
|
|
// static
|
|
CUnknown *
|
|
WINAPI
|
|
CMPEG2PropStreamIdMap::CreateInstance (
|
|
IN IUnknown * pIUnknown,
|
|
IN HRESULT * pHr
|
|
)
|
|
{
|
|
CMpeg2PropStreamMap * pProp ;
|
|
|
|
pProp = new CMPEG2PropStreamIdMap (
|
|
NAME ("CMPEG2PropStreamIdMap"),
|
|
pIUnknown,
|
|
CLSID_MPEG2DemuxPropStreamIdMap,
|
|
pHr
|
|
) ;
|
|
|
|
if (pProp == NULL) {
|
|
* pHr = E_OUTOFMEMORY ;
|
|
}
|
|
|
|
return pProp ;
|
|
}
|
|
|
|
|
|
|
|
|