Concatenate two AVI files using IltmmMultiStreamSource and IltmmMultiStreamTarget Example for C++
#define SOURCE_FILE1 "C:\\Src1.avi"
#define SOURCE_FILE2 "C:\\Src2.wav"
#define DEST_FILE "C:\\Dst.avi"
void Concatenate()
{
IltmmConvert* pConvert1 = NULL;
IltmmConvert* pConvert2 = NULL;
IltmmMultiStreamTarget* pSampleTarget = NULL;
IltmmMultiStreamSource* pSampleSource = NULL;
long lStartLo, lStartHi;
IltmmMediaTypeDisp* pmt = NULL;
IltmmMediaTypeDisp* pInsertedMediaType;
BSTR bstr;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**) &pConvert1);
if(FAILED(hr))
{
AfxMessageBox(_T("Can't instantiate convert library"));
return -1;
}
hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**) &pConvert2);
if(FAILED(hr))
{
AfxMessageBox(_T("Can't instantiate convert library"));
return -1;
}
hr = CoCreateInstance(CLSID_ltmmMultiStreamTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMultiStreamTarget, (void**) &pSampleTarget);
if(FAILED(hr))
{
AfxMessageBox(_T("Can't instantiate convert library"));
return -1;
}
hr = CoCreateInstance(CLSID_ltmmMultiStreamSource, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMultiStreamSource, (void**) &pSampleSource);
if(FAILED(hr))
{
AfxMessageBox(_T("Can't instantiate convert library"));
return -1;
}
// set the start time to be 0
lStartHi = 0;
lStartLo = 0;
// set the input filename
bstr = A2BSTR(SOURCE_FILE1);
pConvert1->put_SourceFile(bstr);
SysFreeString(bstr);
// set the output sample to a target object
pSampleTarget->put_StreamCount(2);
hr = CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**) &pmt);
if(FAILED(hr))
{
AfxMessageBox(_T("Can't instantiate convert library"));
return -1;
}
pmt->put_Type(ltmmMEDIATYPE_Video);
pSampleTarget->SetAcceptedMediaType(0, pmt);
pmt->put_Type(ltmmMEDIATYPE_Audio);
pSampleTarget->SetAcceptedMediaType(1, pmt);
pmt->Release();
pmt = NULL;
// get the inserted media type for the first stream
pSampleTarget->GetAcceptedMediaType(0, &pInsertedMediaType);
pInsertedMediaType->Release();
pInsertedMediaType = NULL;
hr = pConvert1->put_TargetObject(pSampleTarget);
// START the source conversion, so we can get the media sample format
hr = pConvert1->StartConvert();
//INITIALIZE pConvert2
// get the output media sample format and put it into the source object
pSampleSource->put_StreamCount(2);
hr = pSampleTarget->GetConnectedMediaType(0, &pmt);
pSampleSource->SetMediaType(0, pmt);
pmt->Release();
pmt = NULL;
pSampleTarget->GetConnectedMediaType(1, &pmt);
pSampleSource->SetMediaType(1, pmt);
pmt->Release();
pmt = NULL;
// get the inserted media type for the first stream
pSampleSource->GetMediaType(0, &pInsertedMediaType);
pInsertedMediaType->Release();
pInsertedMediaType = NULL;
// set the output filename
bstr = A2BSTR(DEST_FILE);
pConvert2->put_TargetFile(bstr);
SysFreeString(bstr);
pConvert2->put_SourceObject(pSampleSource);
// start the dest conversion
pConvert2->StartConvert();
SetWindowText("Converting file1...");
// convert first file
ConvertFile(pConvert1, pSampleTarget, pSampleSource, &lStartHi, &lStartLo);
/*
Restrict the output format to the media type of the source for the first file
That is because the two files must have the same media type for both video and audio
With video, you have to make sure the files have the same frame rate! Minor changes in
the frame rate might make the connection fail!
The control will tolerate differences in frame rate if you comment the next line
*/
pSampleTarget->GetConnectedMediaType(0, &pmt);
pSampleTarget->SetAcceptedMediaType(0, pmt);
pmt->Release();
pmt = NULL;
pSampleTarget->GetConnectedMediaType(1, &pmt);
pSampleTarget->SetAcceptedMediaType(1, pmt);
pmt->Release();
pmt = NULL;
// change the source file to second file
bstr = A2BSTR(SOURCE_FILE2);
pConvert1->put_SourceFile(bstr);
SysFreeString(bstr);
// start converting again
pConvert1->StartConvert();
SetWindowText("Converting file2...");
// convert second file
ConvertFile(pConvert1, pSampleTarget, pSampleSource, &lStartHi, &lStartLo);
// deliver end of sample to stop the conversion
pSampleSource->DeliverEndOfStream(0, 1000);
pSampleSource->DeliverEndOfStream(1, 1000);
long lState;
pConvert2->get_State(&lState);
if (lState = ltmmConvert_State_Running)
pConvert2->StopConvert();
SetWindowText("Done");
// free the source and target objects
pConvert1->ResetTarget();
pConvert2->ResetSource();
if (pConvert1)
{
pConvert1->Release();
pConvert1 = NULL;
}
if (pConvert2)
{
pConvert2->Release();
pConvert2 = NULL;
}
if (pSampleSource)
{
pSampleSource->Release();
pSampleSource = NULL;
}
if (pSampleTarget)
{
pSampleTarget->Release();
pSampleTarget = NULL;
}
CoUninitialize();
return TRUE; // return TRUE unless you set the focus to a control
}
void CConcatFilesDlg::ConvertFile(IltmmConvert* pConvert1, IltmmMultiStreamTarget* pSampleTarget, IltmmMultiStreamSource* pSampleSource, long* plStartHi , long *plStartLo)
{
IltmmMediaSampleDisp* pmsSrc = NULL;
IltmmMediaSampleDisp* pmsDst = NULL;
long LastStartHi;
long LastStartLo;
long LastStopHi;
long LastStopLo;
long lSampleStream;
HRESULT hr;
LastStopHi = 0;
LastStopLo = 0;
do
{
// get the sample, allowing 10 s for the operation to complete
hr = pSampleTarget->WaitForSample(1000, &lSampleStream);
if (FAILED(hr))
break;
hr = pSampleTarget->GetSample(lSampleStream, 0, &pmsSrc);
if (FAILED(hr))
break;
hr = pSampleSource->GetSampleBuffer(lSampleStream, 2000, &pmsDst);
if (FAILED(hr))
break;
// set the sample time
pmsSrc->GetTime(&LastStartHi, &LastStartLo, &LastStopHi, &LastStopLo);
// get the sample time
pmsDst->SetTime(*plStartHi + LastStartHi, *plStartLo + LastStartLo, *plStartHi + LastStopHi, *plStartLo + LastStopLo);
// copy the data
long lActualDataLength;
pmsSrc->get_ActualDataLength(&lActualDataLength);
VARIANT vBuffer;
pmsSrc->GetData(lActualDataLength, &vBuffer);
pmsDst->SetData(lActualDataLength, vBuffer);
// copy the other flags
VARIANT_BOOL vBool;
hr = pmsSrc->get_Discontinuity(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Discontinuity(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_Preroll(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Preroll(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_SyncPoint(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_SyncPoint(vBool);
if (FAILED(hr))
break;
// release the source sample
pmsSrc->Release();
pmsSrc = NULL;
// deliver the destination sample
pSampleSource->DeliverSample(lSampleStream, 1000, pmsDst);
// release the destination sample
pmsDst->Release();
pmsDst = NULL;
}
while (1);
pConvert1->StopConvert();
*plStartHi = LastStopHi;
*plStartLo = LastStopLo;
}