Add two media sources in topology and display mix video - Windows Media Foundation - ms-media-foundation

I am exploring windows media foundation.
I want to mix and display two video stream in one window.
I am following few of the sample provided by MS.
I am trying to Add multiple media sources to topology, I want to add two media files to topology.
As per the below link, I am following code to add media source in topology:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms701605(v=vs.85).aspx
Below is the code to add source node to the topology:
HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
if (fSelected)
{
// Create the media sink activation object.
hr = CreateMediaSinkActivate(pSD, hVideoWnd, &pSinkActivate);
if (FAILED(hr))
{
goto done;
}
// Add a source node for this stream.
hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode);
if (FAILED(hr))
{
goto done;
}
// Create the output node for the renderer.
hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);
if (FAILED(hr))
{
goto done;
}
// Connect the source node to the output node.
hr = pSourceNode->ConnectOutput(0, pOutputNode, 0);
}
But I am not able to add multiple media source in my topology.
My single file playback is working properly but I am not able to mix and display two files.

I recommend split your task on five step:
1. write code for playing ONE video file. On MSDN there is example code: How to Play Media Files with Media Foundation.
2. research code of WORKABLE player for point, where created MediaSource from video file path(URL).
3. create TWO MediaSource from two video file paths(URL).
4. by function MFCreateAggregateSource create from TWO MediaSource - ONE MediaSource and retuurn MediaSource from method player HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource)
5. call 'hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);' twice: 'hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);' for first video stream and hr = AddOutputNode(pTopology, pSinkActivate, 1, &pOutputNode); for second video stream.
Regards.
P.S. If you will use two video with audio streams, then You will have FOUR streams in Aggregate MediaSource - it could need FIND the stream ID for video stream.
P.S.S It is not easy recommend from viewing only demo code, but in CreateMediaSinkActivate you will find code hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate);. In your code, you must create this Activate before:
// For each stream, create the topology nodes and add them to the topology.
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, hVideoWnd);
if (FAILED(hr))
{
goto done;
}
}
then set this crated Activate as argument for AddBranchToPartialTopology
for example:
hr = MFCreateVideoRendererActivate(hVideoWindow, &pVideoRendererActivate);
// For each stream, create the topology nodes and add them to the topology.
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, pVideoRendererActivate);
if (FAILED(hr))
{
goto done;
}
}
In AddBranchToPartialTopologyyou must write something like this:
HRESULT AddBranchToPartialTopology(
IMFTopology *pTopology, // Topology.
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
DWORD iStream, // Stream index.
IMFActivate* aVideoRendererActivate) // VideoRenderer for video playback.
{
IMFStreamDescriptor *pSD = NULL;
IMFActivate *pSinkActivate = NULL;
IMFTopologyNode *pSourceNode = NULL;
IMFTopologyNode *pOutputNode = NULL;
BOOL fSelected = FALSE;
HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
DWORD iStreamID = 0;
if (fSelected)
{
// Create the media sink activation object.
hr = CreateMediaSinkActivate(pSD, iStreamID, aVideoRendererActivate, &pSinkActivate);
In 'CreateMediaSinkActivate' you must write something like this:
DWORD globalVideoIndex = 0;
HRESULT CreateMediaSinkActivate(
IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor.
DWORD& iStreamID, // ctream index
IMFActivate *pVideoRendererActivate, // Handle to the video renderer activate.
IMFActivate **ppActivate
)
{
IMFMediaTypeHandler *pHandler = NULL;
IMFActivate *pActivate = NULL;
// Get the media type handler for the stream.
HRESULT hr = pSourceSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
// Get the major media type.
GUID guidMajorType;
hr = pHandler->GetMajorType(&guidMajorType);
if (FAILED(hr))
{
goto done;
}
// Create an IMFActivate object for the renderer, based on the media type.
if (MFMediaType_Audio == guidMajorType)
{
// Create the audio renderer.
hr = MFCreateAudioRendererActivate(&pActivate);
}
else if (MFMediaType_Video == guidMajorType)
{
// Share the video renderer.
hr = pVideoRendererActivate->QueryInterface(IID_PPV_ARG(pActivate))
iStreamID = globalVideoIndex++;
}
else
{
// Unknown stream type.
hr = E_FAIL;
// Optionally, you could deselect this stream instead of failing.
}
if (FAILED(hr))
{
goto done;
}
// Return IMFActivate pointer to caller.
*ppActivate = pActivate;
(*ppActivate)->AddRef();
done:
SafeRelease(&pHandler);
SafeRelease(&pActivate);
return hr;
}
In AddBranchToPartialTopology you must write:
// Create the output node for the renderer.
hr = AddOutputNode(pTopology, pSinkActivate, iStreamID, &pOutputNode);
if (FAILED(hr))
{
goto done;
}
for Audio streams iStreamID will zero, but for video stream it will increment from global variable globalVideoIndex.
Idea is that code create Activate for video renderer BEFORE create Topology - it is OK. Then this ONE video renderer activate share by ref pointer between ALL video streams in MediaSource by checking condition if (MFMediaType_Video == guidMajorType). Each VIDEO stream has got unique id from 0 by incrementing global variable globalVideoIndex++ - this id set in method hr = AddOutputNode(pTopology, pSinkActivate, iStreamID, &pOutputNode);. As a result, all video streams will be drawn by ONE video renderer, and video stream with iStreamID is 0 will reference background, while other video streams will additional.

Related

Cortex-M0+ : Can't Jump From Bootloader To App

I'm Working on ATSAMC21 (ATSAMC21J18A) with Cortex-M0+, making my CAN bootloader.My IDE is ATMEL studio.
Flashing my app is Ok but when I jump in i, it failed.(I tryed with debug and without)
In dissaseembly it point to the first of these two line:
*FFFFFFFE ?? ?? ??? Memory out of bounds or read error*
*00000000 a0.32 adds r2, #160*
pc disassembly point
My bootloader space in my linker :
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
My application (or firmware) space in my linker :
MEMORY
{
rom (rx) : ORIGIN = 0x00010000, LENGTH = 0x00030000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Before jumping,
I disabled irq interrupt, defined my entry point and my stack pointer, and change VTOR.
Here is my code to jump:
void JumpToApp(void) {
uint16_t i;
uint32_t startAddress, applicationStack;
/* Check if WDT is locked */
if (!(WDT->CTRLA.reg & WDT_CTRLA_ALWAYSON)) {
/* Disable the Watchdog module */
WDT->CTRLA.reg &= ~WDT_CTRLA_ENABLE;
}
//stop general IT
__disable_irq();
// Disable SysTick
SysTick->CTRL = 0;
// Disable IRQs & clear pending IRQs
for (i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
// Pointer to the Application Section
void (*application_code_entry)(void);
startAddress = FLASH_APP_VADRESS; //HERE 0x00010000, my start App
applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);
application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS + 4)); //HERE 0x00010004
// Rebase the Stack Pointer
__DSB();
__ISB();
__set_MSP(*(uint32_t *)applicationStack); //HERE 0x00010000, my start App
// Rebase the vector table base address
SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
__DSB();
__ISB();
// Jump to user Reset Handler in the application
application_code_entry();
}
I tried to add +1 at my application_code_entry , like a odd Thumb mode, i see this for Cortex-M3 but it don't work, fail in general IT.
Then I rename main() by main_boot()
and Reset_Handler() by Reset_Handler_Boot() (and by changing in propety flag linker the --entry=Reset_Handler_Boot)
But still not jumping.
I don't know what i'm doing bad.May be there is a long jump to do?
Split the RAM?
If somebody have an idea?
Thank You!!!!!!!!!!!!!!!!!!!
Thank you, (it was a mistake :) )but this hard fault doesn't resolve my jump (in fact i Used directly the adress __set_MSP(*(uint32_t *)(FLASH_APP_VADRESS));
My MSP is not 0x0000000, it's 0x20003240 so is it an offset to apply to my new MSP? (see the picture linked)
Here is my code for testing the MSP
ReadMsp=__get_MSP(); //result 0x20003240, before change it
__DSB();
__ISB();
__set_MSP(*(uint32_t *)applicationStack);
// Rebase the vector table base address TODO: use RAM
SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
__DSB();
__ISB();
ReadMsp=__get_MSP(); //result is 0xFFFFFFFC , why ???
__DSB();
__ISB();
__set_MSP(0x00010000);
__DSB();
__ISB();
ReadMsp=__get_MSP(); //result is 0x00010000, better than my same #define FLASH_APP_VADRESS or *(uint32_t *)applicationStack in __MSP
//applicationEntry();
// Load the Reset Handler address of the application
//application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS ));
// Jump to user Reset Handler in the application
application_code_entry();
Should I use (0x20003240 + 0x00010000) for my new MSP?
enter image description here
You are dereferencing the SP stack pointer twice:
applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);
// ... --^
__set_MSP(*(uint32_t *)applicationStack);
// -^
You need to do that only once. The second time sets SP highly likely to zero, resulting to a fault once the stack is used.
I found the answer !!!
Finally to jump, just like atmel say BUT before I needed to uninitialized some module.
So : ATMEL part :
*// Pointer to the Application Section
void (*application_code_entry)(void);
// Rebase the Stack Pointer
__set_MSP(*(uint32_t *)FLASH_APP_VADRESS);
// Rebase the vector table base address TODO: use RAM
SCB->VTOR = ((uint32_t)FLASH_APP_VADRESS & SCB_VTOR_TBLOFF_Msk);
// Load the Reset Handler address of the application
application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)
(FLASH_APP_VADRESS + 4));
// Jump to user Reset Handler in the application
application_code_entry();*
My part before executing this :
*Flash_Deinit(); //flash uninit
config_TC_Deinit(); //time clock uninit, scheduler
can_deinit0(); // module CAN0
can_deinit1(); // module CAN1
Handle_Wdt_Disable();
__disable_irq();
// Disable SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Disable IRQs & clear pending IRQs
for (i = 0; i < 8; i++) {
NVIC->IP[i] = 0x00000000;
}
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICPR[0] = 0xFFFFFFFF;*
I hope it will help someone !!! :)

How to send IMFSample to EVR Media Sink

I want to use EVR standalone, but i failed sending IMFSample to it. codes list below,
//create the video render
IMFActivate* pActive = NULL;
hr = MFCreateVideoRendererActivate(m_hWnd, &pActive);
CHECK_HR(hr);
hr = pActive->ActivateObject(IID_IMFMediaSink,(void**)&m_pVideoSink) ;
CHECK_HR(hr);
hr = m_pVideoSink->GetStreamSinkByIndex(0,&m_pVideoStreamSink) ;
CHECK_HR(hr);
//on Sample ready from a custom mft
hr = m_pVideoStreamSink->ProcessSample(pSample) ;
then i got an E_NOTIMPL error. After several hours struggles, i implemented IMFVideoSampleAllocator:
//get IMFVideoSampleAllocator service
hr = MFGetService(m_pVideoStreamSink,MR_VIDEO_ACCELERATION_SERVICE,IID_PPV_ARGS(&m_pAllocator)) ;
CHECK_HR(hr);
//init IMFVideoSampleAllocator,pType is the negotiated type
hr = m_pAllocator->InitializeSampleAllocator(20,pType) ;
//On sample ready,pSample is the IMFSample from mft
IMFSample* pVideoSample = NULL ;
IMFMediaBuffer* pBuffer = NULL ;
LONGLONG hnsTimeStamp = 0 ;
//copy sample data from pSample to pVideoSample
CHECK_HR(hr = m_pAllocator->AllocateSample(&pVideoSample)) ;
CHECK_HR(hr = pSample->GetSampleTime(&hnsTimeStamp)) ;
CHECK_HR(hr = pVideoSample->SetSampleTime(hnsTimeStamp)) ;
CHECK_HR(hr = pSample->GetBufferByIndex(0,&pBuffer)) ;
CHECK_HR(hr = pVideoSample->AddBuffer(pBuffer)) ;
hr = m_pVideoStreamSink->ProcessSample(pVideoSample) ;
now, every thing works great, but i got only a black screen with no any movie picture drawn on it!
besides, i had added SAR to my code, it worked pretty good.
any help, thx!
Maybe a little late to answer to your question, but anyway ...
I was in a similar situation and I solved it by using a Stream Reader configured with MF_SOURCE_READER_D3D_MANAGER. I took the IDirect3DDeviceManager9 from the Stream Sink the same way you took the allocator:
hr = MFGetService(m_pVideoStreamSink,MR_VIDEO_ACCELERATION_SERVICE,IID_PPV_ARGS(&pD3DManager);
and set it as IUnknown to MF_SOURCE_READER_D3D_MANAGER attribute above.
If you cannot use IMFSourceReader then maybe this link will be helpful:
https://code.google.com/p/webrtc4all/source/browse/trunk/gotham/MFT_WebRTC4All/test/test_evr.cc?r=15
When the pVideoSample is allocated, it already has a buffer for your use; you don't need to add any other buffers.
In your case, my guess is that the originally allocated buffer was used to render the output - which is this case is empty, and hence there's no image.

How to read the weight from a Weight USB Scale

I have a USB weighing from stamps.com (Model 510: http://www.stamps.com/postage-online/digital-postage-scales/)
I was able to find the drivers to make it stand alone online, but my next question is how do I read the weight of the object on the scale in my classic ASP page / VBScript.
Does anyone have any suggestions where I should begin my search?
I'm not sure if this is applicable to your specific model but there's an article at http://nicholas.piasecki.name/blog/2008/11/reading-a-stamps-com-usb-scale-from-c-sharp/ where the author has written C# code to read from the scale because it conforms to basic USB HID (human input device) standards. The author made use of Mike OBrien's HID library https://github.com/mikeobrien/HidLibrary
They start off getting the raw bytes:
HidDeviceData inData;
HidDevice[] hidDeviceList;
HidDevice scale;
hidDeviceList = HidDevices.Enumerate(0x1446, 0x6A73);
if (hidDeviceList.Length > 0)
{
int waitTries;
scale = hidDeviceList[0];
waitTries = 0;
scale.Open();
if (scale.IsConnected)
{
inData = scale.Read(250);
for (int i = 0; i < inData.Data.Length; ++i)
{
Console.WriteLine("Byte {0}: {1:X}", i, inData.Data[i]);
}
}
scale.Close();
scale.Dispose();
}
Then go on to reverse engineer the payload and construct a function to get the weight in ounces:
private void GetStampsComModel2500iScaleWeight(out decimal? ounces, out bool? isStable)
{
HidDeviceData inData;
HidDevice[] hidDeviceList;
HidDevice scale;
isStable = null;
ounces = null;
hidDeviceList = HidDevices.Enumerate(0x1446, 0x6A73);
if (hidDeviceList.Length > 0)
{
int waitTries;
scale = hidDeviceList[0];
waitTries = 0;
scale.Open();
// For some reason, the scale isn't always immediately available
// after calling Open(). Let's wait for a few milliseconds before
// giving up.
while (!scale.IsConnected && waitTries < 10)
{
Thread.Sleep(50);
waitTries++;
}
if (scale.IsConnected)
{
inData = scale.Read(250);
ounces = (Convert.ToDecimal(inData.Data[4]) +
Convert.ToDecimal(inData.Data[5]) * 256) / 10;
isStable = inData.Data[1] == 0x4;
}
scale.Close();
scale.Dispose();
}
}
In order to read the weight from your classic ASP page/VBScript (on the server, right?) the easiest solution looks to be turning the working C# class into a COM component. There are tutorials you can follow to create the C# COM Component and register it on the server, then you would call it from VBScript like:
Dim app
Set app = Server.CreateObject("MyScaleComponent")

OutOfMemoryError during heuristic search

I'm writing a program to solve an 8 tile sliding puzzle for an AI class. in theory this is pretty easy, but the number of node states generated is pretty large (estimated 180,000 or so). We're comparing different heuristic functions in class, so my code has to be able to handle even some very inefficient functions. I'm getting "OutOfMemoryError: Java heap space" when using java's PriorityQueue class. Heres the relevant code withing my solver function: (the error is on the openList.add(temp); line)
public void solve(char[] init,int searchOrder)
{
State initial = new State(init,searchOrder); //create initial state
openList = new PriorityQueue<State>(); //create open list
closedList = new LinkedList<State>(); // create closed list
generated = new HashSet(); //Keeps track of all nodes generated to cut down search time
openList.add(initial); //add initial state to the open list
State expanded,temp = null,solution = null; //State currently being expanded
int nodesStored = 0, nodesExpanded = 0;
boolean same; //used for checking for state redundancy
TreeGeneration:
while(openList.size() > 0)
{
expanded = openList.poll();
closedList.addLast(expanded);
for (int k = 0; k < 4; k++)
{
if (k == 0)
{
temp = expanded.moveLeft();
}
else if (k == 1)
{
temp = expanded.moveRight();
}
else if (k == 2)
{
temp = expanded.moveAbove();
}
else
{
temp = expanded.moveBelow();
}
if(temp.isSolution())
{
solution = temp;
nodesStored = openList.size() + closedList.size();
nodesExpanded = closedList.size();
break TreeGeneration;
}
if(!generated.contains(temp))
{
// System.out.println(temp.toString());
openList.add(temp); // error here
generated.add(temp);
}
// System.out.println(openList.toString());
}
}
Am I doing something wrong here, or should I be using something else to handle this quantity of data? Thanks.
By default, JVM starts with 64 MB heap space, you can increase this amount by passing a parameter like below;
java -Xmx1024m YOUR_CLASS
this gives 1024 MB heap space in memory, you can change the amount of memory as you need.
If you are using NetBeans, Netbeans doesn't scale heap space automatically, you can achieve this by following below steps;
1- Right click on your project
2- Navigate to Set Configuration -> Customize
3-Add -Xmx256m into VM Options then click Ok
Now, you can run your project with custom heap space.

DirectShow API for analog tuning to put a frequency?

I'm looking for the interfaces in DirectShow that will let me push a frequency only.
The IAMTVTuner interface allows you to put_channel but this requires pretuning your card. I want to just specify the frequency to tune to. Is this possible with analog tuning? (you can do it easy with the interfaces for digital streams however).
I think this codeproject link should help you
Here is the code:
// It is assumed that you have constructed the complete TV tuner Graph
// of your Device.And will use this function to set custom frequencies
// or to fine tune a tuned TV channel.Please also make sure to set the
// appropriate Video standard and contry code before calling this function.
#define INSTANCEDATA_OF_PROPERTY_PTR(x) ((PKSPROPERTY((x))) + 1)
#define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY))
HRESULT SetFrequency(long Freq)
{
HRESULT hr;
DWORD dwSupported=0;
// Query the IKsPropertySet on your Device TV Tuner Filter.
// m_pTvtuner is IBaseFilter Pointer of your TV Tuner Filter.
CComPtr m_pKSProp;
hr = m_pTvtuner->QueryInterface(IID_IKsPropertySet, (void**)&m_pKSProp);
if (FAILED(hr))
return E_FAIL;
KSPROPERTY_TUNER_MODE_CAPS_S ModeCaps;
KSPROPERTY_TUNER_FREQUENCY_S Frequency;
memset(&ModeCaps,0,sizeof(KSPROPERTY_TUNER_MODE_CAPS_S));
memset(&Frequency,0,sizeof(KSPROPERTY_TUNER_FREQUENCY_S));
ModeCaps.Mode = AMTUNER_MODE_TV;
// Check either the Property is supported or not by the Tuner drivers
hr = m_pKSProp->QuerySupported(PROPSETID_TUNER,
KSPROPERTY_TUNER_MODE_CAPS,&dwSupported);
if(SUCCEEDED(hr) && dwSupported&KSPROPERTY_SUPPORT_GET)
{
DWORD cbBytes=0;
hr = m_pKSProp->Get(PROPSETID_TUNER,KSPROPERTY_TUNER_MODE_CAPS,
INSTANCEDATA_OF_PROPERTY_PTR(&ModeCaps),
INSTANCEDATA_OF_PROPERTY_SIZE(ModeCaps),
&ModeCaps,
sizeof(ModeCaps),
&cbBytes);
}
else
return E_FAIL;
Frequency.Frequency=Freq;
if(ModeCaps.Strategy==KS_TUNER_STRATEGY_DRIVER_TUNES)
Frequency.TuningFlags=KS_TUNER_TUNING_FINE;
else
Frequency.TuningFlags=KS_TUNER_TUNING_EXACT;
// Here the real magic starts
if(Freq>=ModeCaps.MinFrequency && Freq<=ModeCaps.MaxFrequency)
{
hr = m_pKSProp->Set(PROPSETID_TUNER,
KSPROPERTY_TUNER_FREQUENCY,
INSTANCEDATA_OF_PROPERTY_PTR(&Frequency),
INSTANCEDATA_OF_PROPERTY_SIZE(Frequency),
&Frequency,
sizeof(Frequency));
if(FAILED(hr))
return E_FAIL;
}
else
return E_FAIL;
return S_OK;
}

Resources