About directshow: Why can't I release it thoroughly? - visual-c++

Everytime I load a new movie and then close it, I find that the used memory of my programme increases by 20-50M. I has tried many ways to release it, but none of them works. ( I even used CoUninitialize(); )
Here's the main part of the code.
// DirectShow interfaces
IGraphBuilder *pGB = NULL;
IMediaControl *pMC = NULL;
IMediaEventEx *pME = NULL;
IBasicAudio *pBA = NULL;
IMediaSeeking *pMS = NULL;
IMediaPosition *pMP = NULL;
// VMR9 interfaces
IVMRWindowlessControl9 *pWC = NULL;
#define JIF(x) if (FAILED(hr=(x))) \
{Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n\0"), hr); return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile)
{
HRESULT hr;
// hr = CoInitialize(NULL);
// Get the interface for DirectShow's GraphBuilder
JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGB));
if (SUCCEEDED(hr))
{
IBaseFilter *pVmr;
// Create the VMR and add it to the filter graph.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (SUCCEEDED(hr))
{
hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer 9");
//Add LAV Filters to filter graph
IBaseFilter *pLavSplitterSource, *pLavVideoDecoder, *pLavAudioDecoder, *pAudioRender;
IFileSourceFilter *pFileSourceFilter;
hr = AddFilterByCLSID(pGB, CLSID_LavSplitter_Source, &pLavSplitterSource, L"Lav Splitter Source");
hr = pLavSplitterSource->QueryInterface(IID_IFileSourceFilter, (void **)&pFileSourceFilter);
hr = pFileSourceFilter->Load(szFile, NULL);
hr = AddFilterByCLSID(pGB, CLSID_LavVideoDecoder, &pLavVideoDecoder, L"Lav Video Decoder");
hr = AddFilterByCLSID(pGB, CLSID_LavAudioDecoder, &pLavAudioDecoder, L"Lav Audio Decoder");
hr = AddFilterByCLSID(pGB, CLSID_DSoundRender, &pAudioRender, L"DirectSound Audio render");
if (SUCCEEDED(hr))
{
// Set the rendering mode and number of streams
IVMRFilterConfig9 *pConfig;
JIF(pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig));
JIF(pConfig->SetRenderingMode(VMR9Mode_Windowless));
hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC);
if (SUCCEEDED(hr))
{
JIF(pWC->SetVideoClippingWindow(hVideo));
JIF(pWC->SetBorderColor(RGB(0, 0, 0)));
}
SAFE_RELEASE(pConfig);
SAFE_RELEASE(pVmr);
}
}
// Render the file programmatically to use the VMR9 as renderer.
// Pass TRUE to create an audio renderer also.
if (FAILED(hr = RenderFileToVideoRenderer(pGB, szFile, FALSE))) return hr;
// QueryInterface for DirectShow interfaces
JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));
JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));
JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS));
JIF(pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP));
JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA));
// Have the graph signal event via window callbacks for performance
JIF(pME->SetNotifyWindow((OAHWND)hVideo, WM_GRAPHNOTIFY, 0));
JIF(pMC->Run());
}
return hr;
}
void CloseInterfaces(void)
{
HRESULT hr;
// Stop media playback
if (pMC)
hr = pMC->Stop();
// Disable event callbacks
if (pME)
hr = pME->SetNotifyWindow((OAHWND)NULL, 0, 0);
// Enumerate the filters And remove them
IEnumFilters *pEnum = NULL;
hr = pGB->EnumFilters(&pEnum);
if (SUCCEEDED(hr))
{
IBaseFilter *pFilter = NULL;
while (S_OK == pEnum->Next(1, &pFilter, NULL))
{
// Remove the filter.
pGB->RemoveFilter(pFilter);
// Reset the enumerator.
pEnum->Reset();
pFilter->Release();
}
pEnum->Release();
}
// Release and zero DirectShow interfaces
SAFE_RELEASE(pME);
SAFE_RELEASE(pMS);
SAFE_RELEASE(pMP);
SAFE_RELEASE(pMC);
SAFE_RELEASE(pBA);
SAFE_RELEASE(pWC);
SAFE_RELEASE(pGB);
// CoUninitialize();
}
I use LAV Filters as the decoder. Platform: win7 vs2013
This question has bothered me for more than a week. I will appreciate it very much if you solve my problem. Thanks a lot!

Related

Audio Frames repeating in AVFramework created *.mov file via AVAsset

I am running into some problems trying to create a ProRes encoded mov file using the AVFramework framework, and AVAsset.
On OSX 10.10.5, using XCode 7, linking against 10.9 libraries.
So far I have managed to create valid ProRes files that contain both video and multiple channels of audio.
( I am creating multiple tracks of uncompressed 48K, 16-bit PCM Audio)
Adding the Video Frames work well, and adding the Audio frames works well, or at least succeeds in the code.
However when i play the file back, it appears as though the audio frames are repeated, in 12,13,14, or 15 frame sequences.
Looking at the wave form, from the *.mov it is easy to see the repeated audio...
That is to say, the first 13 or X video frames all contain exactly the same audio, this is then again repeated for the next X, and then again and again and again etc...
The Video is fine, it is just the Audio that appears to be looping/repeating.
The issue appears no matter how many audio channels/ tracks I use as the source, I have tested using just 1 track and also using 4 and 8 tracks.
It is independent of what format and amount of samples i feed to the system, ie using, 720p60, 1080p23, and 1080i59 all exhibit the same incorrect behavior.
well actually the 720p captures appears to repeat the audio frames 30 or 31 times, and the 1080 formats only repeat the audio frames 12 or 13 times,
But i am definitely submitting different audio data to the Audio encode/SampleBuffer create process, as i have logged this in great detail ( tho it is not shown in the code below)
I have tried a number of different things to modify the code and expose the issue, but had no success, hence i am asking here, and hopefully someone can either see an issue with my code or give me some info with regards to this problem.
The code i am using is as follows:
int main(int argc, const char * argv[])
{
#autoreleasepool
{
NSLog(#"Hello, World! - Welcome to the ProResCapture With Audio sample app. ");
OSStatus status;
AudioStreamBasicDescription audioFormat;
CMAudioFormatDescriptionRef audioFormatDesc;
// OK so lets include the hardware stuff first and then we can see about doing some actual capture and compress stuff
HARDWARE_HANDLE pHardware = sdiFactory();
if (pHardware)
{
unsigned long ulUpdateType = UPD_FMT_FRAME;
unsigned long ulFieldCount = 0;
unsigned int numAudioChannels = 4; //8; //4;
int numFramesToCapture = 300;
gBFHancBuffer = (unsigned int*)myAlloc(gHANC_SIZE);
int audioSize = 2002 * 4 * 16;
short* pAudioSamples = (short*)new char[audioSize];
std::vector<short*> vecOfNonInterleavedAudioSamplesPtrs;
for (int i = 0; i < 16; i++)
{
vecOfNonInterleavedAudioSamplesPtrs.push_back((short*)myAlloc(2002 * sizeof(short)));
}
bool bVideoModeIsValid = SetupAndConfigureHardwareToCaptureIncomingVideo();
if (bVideoModeIsValid)
{
gBFBytes = (BLUE_UINT32*)myAlloc(gGoldenSize);
bool canAddVideoWriter = false;
bool canAddAudioWriter = false;
int nAudioSamplesWritten = 0;
// declare the vars for our various AVAsset elements
AVAssetWriter* assetWriter = nil;
AVAssetWriterInput* assetWriterInputVideo = nil;
AVAssetWriterInput* assetWriterAudioInput[16];
AVAssetWriterInputPixelBufferAdaptor* adaptor = nil;
NSURL* localOutputURL = nil;
NSError* localError = nil;
// create the file we are goijmng to be writing to
localOutputURL = [NSURL URLWithString:#"file:///Volumes/Media/ProResAVCaptureAnyFormat.mov"];
assetWriter = [[AVAssetWriter alloc] initWithURL: localOutputURL fileType:AVFileTypeQuickTimeMovie error:&localError];
if (assetWriter)
{
assetWriter.shouldOptimizeForNetworkUse = NO;
// Lets configure the Audio and Video settings for this writer...
{
// Video First.
// Add a video input
// create a dictionary with the settings we want ie. Prores capture and width and height.
NSMutableDictionary* videoSettings = [NSMutableDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecAppleProRes422, AVVideoCodecKey,
[NSNumber numberWithInt:width], AVVideoWidthKey,
[NSNumber numberWithInt:height], AVVideoHeightKey,
nil];
assetWriterInputVideo = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo outputSettings:videoSettings];
adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:assetWriterInputVideo
sourcePixelBufferAttributes:nil];
canAddVideoWriter = [assetWriter canAddInput:assetWriterInputVideo];
}
{ // Add a Audio AssetWriterInput
// Create a dictionary with the settings we want ie. Uncompressed PCM audio 16 bit little endian.
NSMutableDictionary* audioSettings = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:48000.0], AVSampleRateKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
[NSNumber numberWithUnsignedInteger:1], AVNumberOfChannelsKey,
nil];
// OR use... FillOutASBDForLPCM(AudioStreamBasicDescription& outASBD, Float64 inSampleRate, UInt32 inChannelsPerFrame, UInt32 inValidBitsPerChannel, UInt32 inTotalBitsPerChannel, bool inIsFloat, bool inIsBigEndian, bool inIsNonInterleaved = false)
UInt32 inValidBitsPerChannel = 16;
UInt32 inTotalBitsPerChannel = 16;
bool inIsFloat = false;
bool inIsBigEndian = false;
UInt32 inChannelsPerTrack = 1;
FillOutASBDForLPCM(audioFormat, 48000.00, inChannelsPerTrack, inValidBitsPerChannel, inTotalBitsPerChannel, inIsFloat, inIsBigEndian);
status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault,
&audioFormat,
0,
NULL,
0,
NULL,
NULL,
&audioFormatDesc
);
for (int t = 0; t < numAudioChannels; t++)
{
assetWriterAudioInput[t] = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioSettings];
canAddAudioWriter = [assetWriter canAddInput:assetWriterAudioInput[t] ];
if (canAddAudioWriter)
{
assetWriterAudioInput[t].expectsMediaDataInRealTime = YES; //true;
[assetWriter addInput:assetWriterAudioInput[t] ];
}
}
CMFormatDescriptionRef myFormatDesc = assetWriterAudioInput[0].sourceFormatHint;
NSString* medType = [assetWriterAudioInput[0] mediaType];
}
if(canAddVideoWriter)
{
// tell the asset writer to expect media in real time.
assetWriterInputVideo.expectsMediaDataInRealTime = YES; //true;
// add the Input(s)
[assetWriter addInput:assetWriterInputVideo];
// Start writing the frames..
BOOL success = true;
success = [assetWriter startWriting];
CMTime startTime = CMTimeMake(0, fpsRate);
[assetWriter startSessionAtSourceTime:kCMTimeZero];
// [assetWriter startSessionAtSourceTime:startTime];
if (success)
{
startOurVideoCaptureProcess();
// **** possible enhancement is to use a pixelBufferPool to manage multiple buffers at once...
CVPixelBufferRef buffer = NULL;
int kRecordingFPS = fpsRate;
bool frameAdded = false;
unsigned int bufferID;
for( int i = 0; i < numFramesToCapture; i++)
{
printf("\n");
buffer = pixelBufferFromCard(bufferID, width, height, memFmt); // This function to get a CVBufferREf From our device, as well as getting the Audio data
while(!adaptor.assetWriterInput.readyForMoreMediaData)
{
printf(" readyForMoreMediaData FAILED \n");
}
if (buffer)
{
// Add video
printf("appending Frame %d ", i);
CMTime frameTime = CMTimeMake(i, kRecordingFPS);
frameAdded = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
if (frameAdded)
printf("VideoAdded.....\n ");
// Add Audio
{
// Do some Processing on the captured data to extract the interleaved Audio Samples for each channel
struct hanc_decode_struct decode;
DecodeHancFrameEx(gBFHancBuffer, decode);
int nAudioSamplesCaptured = 0;
if(decode.no_audio_samples > 0)
{
printf("completed deCodeHancEX, found %d samples \n", ( decode.no_audio_samples / numAudioChannels) );
nAudioSamplesCaptured = decode.no_audio_samples / numAudioChannels;
}
CMTime audioTimeStamp = CMTimeMake(nAudioSamplesWritten, 480000); // (Samples Written) / sampleRate for audio
// This function repacks the Audio from interleaved PCM data a vector of individual array of Audio data
RepackDecodedHancAudio((void*)pAudioSamples, numAudioChannels, nAudioSamplesCaptured, vecOfNonInterleavedAudioSamplesPtrs);
for (int t = 0; t < numAudioChannels; t++)
{
CMBlockBufferRef blockBuf = NULL; // *********** MUST release these AFTER adding the samples to the assetWriter...
CMSampleBufferRef cmBuf = NULL;
int sizeOfSamplesInBytes = nAudioSamplesCaptured * 2; // always 16bit memory samples...
// Create sample Block buffer for adding to the audio input.
status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
(void*)vecOfNonInterleavedAudioSamplesPtrs[t],
sizeOfSamplesInBytes,
kCFAllocatorNull,
NULL,
0,
sizeOfSamplesInBytes,
0,
&blockBuf);
if (status != noErr)
NSLog(#"CMBlockBufferCreateWithMemoryBlock error");
status = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault,
blockBuf,
TRUE,
0,
NULL,
audioFormatDesc,
nAudioSamplesCaptured,
audioTimeStamp,
NULL,
&cmBuf);
if (status != noErr)
NSLog(#"CMSampleBufferCreate error");
// leys check if the CMSampleBuf is valid
bool bValid = CMSampleBufferIsValid(cmBuf);
// examine this values for debugging info....
CMTime cmTimeSampleDuration = CMSampleBufferGetDuration(cmBuf);
CMTime cmTimePresentationTime = CMSampleBufferGetPresentationTimeStamp(cmBuf);
if (status != noErr)
NSLog(#"Invalid Buffer found!!! possible CMSampleBufferCreate error?");
if(!assetWriterAudioInput[t].readyForMoreMediaData)
printf(" readyForMoreMediaData FAILED - Had to Drop a frame\n");
else
{
if(assetWriter.status == AVAssetWriterStatusWriting)
{
BOOL r = YES;
r = [assetWriterAudioInput[t] appendSampleBuffer:cmBuf];
if (!r)
{
NSLog(#"appendSampleBuffer error");
}
else
success = true;
}
else
printf("AssetWriter Not ready???!? \n");
}
if (cmBuf)
{
CFRelease(cmBuf);
cmBuf = 0;
}
if(blockBuf)
{
CFRelease(blockBuf);
blockBuf = 0;
}
}
nAudioSamplesWritten = nAudioSamplesWritten + nAudioSamplesCaptured;
}
if(success)
{
printf("Audio tracks Added..");
}
else
{
NSError* nsERR = [assetWriter error];
printf("Problem Adding Audio tracks / samples");
}
printf("Success \n");
}
if (buffer)
{
CVBufferRelease(buffer);
}
}
}
AVAssetWriterStatus sta = [assetWriter status];
CMTime endTime = CMTimeMake((numFramesToCapture-1), fpsRate);
if (audioFormatDesc)
{
CFRelease(audioFormatDesc);
audioFormatDesc = 0;
}
// Finish the session
StopVideoCaptureProcess();
[assetWriterInputVideo markAsFinished];
for (int t = 0; t < numAudioChannels; t++)
{
[assetWriterAudioInput[t] markAsFinished];
}
[assetWriter endSessionAtSourceTime:endTime];
bool finishedSuccessfully = [assetWriter finishWriting];
if (finishedSuccessfully)
NSLog(#"Writing file ended successfully \n");
else
{
NSLog(#"Writing file ended WITH ERRORS...");
sta = [assetWriter status];
if (sta != AVAssetWriterStatusCompleted)
{
NSError* nsERR = [assetWriter error];
printf("investoigating the error \n");
}
}
}
else
{
NSLog(#"Unable to Add the InputVideo Asset Writer to the AssetWriter, file will not be written - Exiting");
}
if (audioFormatDesc)
CFRelease(audioFormatDesc);
}
for (int i = 0; i < 16; i++)
{
if (vecOfNonInterleavedAudioSamplesPtrs[i])
{
bfFree(2002 * sizeof(unsigned short), vecOfNonInterleavedAudioSamplesPtrs[i]);
vecOfNonInterleavedAudioSamplesPtrs[i] = nullptr;
}
}
}
else
{
NSLog(#"Unable to find a valid input signal - Exiting");
}
if (pAudioSamples)
delete pAudioSamples;
}
}
return 0;
}
It's a very basic sample that connects to some special hardware ( code for that is left out)
It grabs frames of video and audio, and then there is the processing for the Audio to go from interleaved PCM to the individual Array's of PCM data for each track
and then each buffer is added to the appropriate track, be it video or audio...
Lastly the AvAsset stuff is finished and closed and i exit and clean up.
Any help will be most appreciated,
Cheers,
James
Well i finally found a working solution for this problem.
The solution comes in 2 parts:
I moved from using CMAudioSampleBufferCreateWithPacketDescriptions
to using CMSampleBufferCreate(..) and the appropriate arguments to that function call.
Initially when experiementing with CMSampleBufferCreate i was mis-using some of the arguments and it was giving me the same results as i initially outlined here, but with careful examination of the values i was passing for the CMSampleTimingInfo struct - specifically the duration part, i eventually got everything working correctly!!
So it appears that i was creating the CMBlockBufferRef correctly, but i needed to take more care when using this to create the CMSampleBufRef that i was passing to the AVAssetWriterInput!
Hope this helps someone else, as it was a nasty one for me to solve!
James

How do I enable depth test in Direct3D 11?

I am experimenting with Direct3D 11 API and I am not very familiar with D3D. I have always OpenGL for my projects.
So far I've managed to draw simple triangle. Now I want to draw some more complicated objects but there is a problem. I don't know how to enable depth test (or does it use totally different concept?). I am getting something like this:
I initialize D3D like this:
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.Windowed = true;
HRESULT result = D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE::D3D_DRIVER_TYPE_HARDWARE,
NULL,
0,
NULL,
0,
D3D11_SDK_VERSION,
&swapChainDesc,
&SwapChain,
&Device,
NULL,
&DeviceContext);
if (result != S_OK)
throw "Direct3D initialization error";
ID3D11Texture2D *backBufferTexture;
result = SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)&backBufferTexture);
if (result != S_OK)
{
[error handling here]
}
result = Device->CreateRenderTargetView(backBufferTexture, NULL, &BackBuffer);
backBufferTexture->Release();
if (result != S_OK)
{
[error handling here]
}
DeviceContext->OMSetRenderTargets(1, &BackBuffer, NULL);
After that comes shader loading, matrix setup, vertex and index buffers initialization. I bet there is something missing here but don't know what.
Ok, I have found out what was missing. Depth buffer needs to be created explicitly. What's interesting, depth and stencil buffers are merged into one buffer.
D3D11_TEXTURE2D_DESC depthTextureDesc;
ZeroMemory(&depthTextureDesc, sizeof(depthTextureDesc));
depthTextureDesc.Width = width;
depthTextureDesc.Height = height;
depthTextureDesc.MipLevels = 1;
depthTextureDesc.ArraySize = 1;
depthTextureDesc.SampleDesc.Count = 1;
depthTextureDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *DepthStencilTexture;
result = Device->CreateTexture2D(&depthTextureDesc, NULL, &DepthStencilTexture);
if (result != S_OK) [error handling code]
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
ZeroMemory(&dsvDesc, sizeof(dsvDesc));
dsvDesc.Format = depthTextureDesc.Format;
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
result = Device->CreateDepthStencilView(DepthStencilTexture, &dsvDesc, &DepthBuffer);
DepthStencilTexture->Release();
if (result != S_OK) [error handling code]
DeviceContext->OMSetRenderTargets(1, &BackBuffer, DepthBuffer);
Of course, clearing of that buffer is needed every frame.
DeviceContext->ClearDepthStencilView(DepthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

Calculating width of unicode character in DirectWrite using GetDesignGlyphMetrics

I am working on a GDI to DirectWrite migration project.
I want to calculate width of each unicode character , on GDI this is acomplished using GetCharWidth.
On msdn blog i found that replacement for GetCharWidth of GDI is GetDesignGlyphMetrics .
Can anyone tell me how to use this function GetDesignGlyphMetrics in order to get DWRITE_GLYPH_METRICS?
How to instantiate its first parameter UINT16 const* glyphIndices?
You can get the glyphindices by IDWriteFontFace::GetGlyphIndices
I pick some code from my project, this is just an example show you how to use this function, if you want to use it in your project, you should do some refactoring, move the XXXCreate function to the initialize part of your code. for example, you don't need to create the DWriteFacotry every time when you call this function(GetCharWidth). and release the dynamic array to avoid memory leaks.
IDWriteFactory* g_pDWriteFactory = NULL;
IDWriteFontFace* g_pFontFace = NULL;
IDWriteFontFile* g_pFontFile = NULL;
IDWriteTextFormat* g_pTextFormat = NULL;
VOID GetCharWidth(wchar_t c)
{
// Create Direct2D Factory
HRESULT hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&g_pD2DFactory
);
if(FAILED(hr))
{
MessageBox(NULL, L"Create Direct2D factory failed!", L"Error", 0);
return;
}
// Create font file reference
const WCHAR* filePath = L"C:/Windows/Fonts/timesbd.ttf";
hr = g_pDWriteFactory->CreateFontFileReference(
filePath,
NULL,
&g_pFontFile
);
if(FAILED(hr))
{
MessageBox(NULL, L"Create font file reference failed!", L"Error", 0);
return;
}
// Create font face
IDWriteFontFile* fontFileArray[] = { g_pFontFile };
g_pDWriteFactory->CreateFontFace(
DWRITE_FONT_FACE_TYPE_TRUETYPE,
1,
fontFileArray,
0,
DWRITE_FONT_SIMULATIONS_NONE,
&g_pFontFace
);
if(FAILED(hr))
{
MessageBox(NULL, L"Create font file face failed!", L"Error", 0);
return;
}
wchar_t textString[] = {c, '\0'};
// Get text length
UINT32 textLength = (UINT32)wcslen(textString);
UINT32* pCodePoints = new UINT32[textLength];
ZeroMemory(pCodePoints, sizeof(UINT32) * textLength);
UINT16* pGlyphIndices = new UINT16[textLength];
ZeroMemory(pGlyphIndices, sizeof(UINT16) * textLength);
for(unsigned int i = 0; i < textLength; ++i)
{
pCodePoints[i] = textString[i];
}
// Get glyph indices
hr = g_pFontFace->GetGlyphIndices(
pCodePoints,
textLength,
pGlyphIndices
);
if(FAILED(hr))
{
MessageBox(NULL, L"Get glyph indices failed!", L"Error", 0);
return;
}
DWRITE_GLYPH_METRICS* glyphmetrics = new DWRITE_GLYPH_METRICS[textLength];
g_pFontFace->GetDesignGlyphMetrics(pGlyphIndices, textLength, glyphmetrics);
// do your calculation here
delete []glyphmetrics;
glyphmetrics = NULL;
}

Rotating an Image of type IImage* [Windows Mobile]

Any Thoughts on how i can accomplish a 90 degree rotation on this image? The followin is my code snippet.
HWND hwnd = GetActiveWindow();
HMODULE hmod = GetModuleHandle(NULL);
HRSRC hResInfo = FindResource(hmod,MAKEINTRESOURCE(IDR_JPEG2),_T("JPEG"));
DWORD imagesize = SizeofResource(hmod,hResInfo);
HGLOBAL hResData = LoadResource(hmod,hResInfo);
if(hResData == NULL)
return -1;
LPVOID resptr = LockResource(hResData);
IImagingFactory *imgF = NULL;
IImage *iimg = NULL;
HDC hdc = pDC->GetSafeHdc();
int iWidth = GetSystemMetrics(SM_CXSCREEN);
int iHeight = GetSystemMetrics(SM_CYSCREEN);
::CoInitializeEx(NULL, ::COINIT_MULTITHREADED);//Initializing the COM object. It is required before
if (CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_IImagingFactory,(void **)&imgF) == S_OK)
{
HRESULT hresult = imgF->CreateImageFromBuffer(resptr,imagesize,BufferDisposalFlagNone,&iimg);
RECT rect;
rect.bottom = iHeight;
rect.left = 0;
rect.right = iWidth;
rect.top = 0;
if(iWidth > iHeight)
{
//Rotation should take place here
}
iimg->Draw(hdc,&rect,NULL);
}
The argument to this function is of the type CDC* pDC.
It is very easy to do:
One has to call 'QueryInterface' on 'iimg' for IBasicBitmapOps
Given its result, use the Rotate method to accomplish your goal
I hope this will help you
Adding on to #kids_fox's answer. This what i did to accomplish the rotation. Hope this helps anyone who has/is/will be facing this problem. Add this onto the function in the question.
IImage *pImage = NULL,
IBitmapImage *pBitmap = NULL;
IBitmapImage *pBitmapRotated = NULL; //Rotated Bitmap
IBasicBitmapOps *pBasicBitmapOps = NULL; //BitmapOps
HRESULT hr = S_FALSE
if(pImgFactory->CreateBitmapFromImage(iimg ,0,0,PixelFormatDontCare,InterpolationHintDefault,&pBitmap) == S_OK)
{
if(pBitmap->QueryInterface( IID_IBasicBitmapOps, (void**)&pBasicBitmapOps ) == S_OK)
{
if(pBasicBitmapOps->Rotate( rotateDegree, InterpolationHintBilinear, &pBitmapRotated) == S_OK)
{
hr = pBitmapRotated->QueryInterface(IID_IImage, ( void**)&pImage);
pBitmapRotated->Release();
pBitmapRotated = NULL;
}
pBasicBitmapOps->Release();
pBasicBitmapOps = NULL;
}
pBitmap->Release();
pBitmap = NULL;
}
//Now Draw the image
pImage->Draw(hdc,&rect,NULL);

Duration of an amr audio file

i want to find the duration of an audio file of type "amr" without converting it to other audio formats
with any way?
AK
I have coded the following in objective-C to get the duration of a movie. This can similarly be used to get the duration of audio too:
-(double)durationOfMovieAtPath:(NSString*)inMoviePath
{
double durationToReturn = -1;
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:inMoviePath])
{
av_register_all();
AVFormatContext *inMovieFormat = NULL;
inMovieFormat = avformat_alloc_context();
int errorCode = av_open_input_file(&inMovieFormat, [inMoviePath UTF8String], NULL, 0, NULL);
//double durationToReturn = (double)inMovieFormat->duration / AV_TIME_BASE;
if (0==errorCode)
{
// only on success
int numberOfStreams = inMovieFormat->nb_streams;
AVStream *videoStream = NULL;
for (int i=0; i<numberOfStreams; i++)
{
AVStream *st = inMovieFormat->streams[i];
if (st->codec->codec_type == CODEC_TYPE_VIDEO)
{
videoStream = st;
break;
}
}
double divideFactor;
// The duraion in AVStream is set in accordance with the time_base of AVStream, so we need to fetch back the duration using this factor
divideFactor = (double)1/rationalToDouble(videoStream->time_base);
if (NULL!=videoStream)
durationToReturn = (double)videoStream->duration / divideFactor;
//DEBUGLOG (#"Duration of movie at path: %# = %0.3f", inMoviePath, durationToReturn);
}
else
{
DEBUGLOG (#"avformat_alloc_context error code = %d", errorCode);
}
if (nil!=inMovieFormat)
{
av_close_input_file(inMovieFormat);
//av_free(inMovieFormat);
}
}
return durationToReturn;
}
Change the CODEC_TYPE_VIDEO to CODEC_TYPE_AUDIO and I think it should work for you.

Resources