Concatenate two AVI files using IltmmMultiStreamSource and IltmmMultiStreamTarget Example for C

int Concatenate()
{
   IltmmConvert* pConvert1 = NULL;
   IltmmConvert* pConvert2 = NULL;
   IltmmMultiStreamTarget* pMSTarget = NULL;
   IltmmMultiStreamSource* pMSSource = NULL;
   long lStartLo, lStartHi;
   IltmmMediaTypeDisp* pmt = NULL;
   IltmmMediaTypeDisp* pInsertedMediaType;
   BSTR  bstr;
   HRESULT hr;
   long lState;

   CoInitialize(NULL);

   hr = CoCreateInstance(&CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmConvert, (void**) &pConvert1);
   if(FAILED(hr))
   {
      MessageBox(0, "Can't instantiate convert library", "Error", 0);
      return -1;
   }

   hr = CoCreateInstance(&CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmConvert, (void**) &pConvert2);
   if(FAILED(hr))
   {
      MessageBox(0, "Can't instantiate convert library", "Error", 0);
      return -1;
   }

   hr = CoCreateInstance(&CLSID_ltmmMultiStreamTarget, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmMultiStreamTarget, (void**) &pMSTarget);
   if(FAILED(hr))
   {
      MessageBox(0, "Can't instantiate convert library", "Error", 0);
      return -1;
   }

   hr = CoCreateInstance(&CLSID_ltmmMultiStreamSource, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmMultiStreamSource, (void**) &pMSSource);
   if(FAILED(hr))
   {
      MessageBox(0, "Can't instantiate convert library", "Error", 0);
      return -1;
   }

   // set the start time to be 0
   lStartHi = 0;
   lStartLo = 0;

   // set the input filename
   bstr = T2OLE("c:\\Src1.avi");
   IltmmConvert__put_SourceFile(pConvert1, bstr);
   SysFreeString(bstr);
   // set the output sample to a target object
   IltmmMultiStreamTarget__put_StreamCount(pMSTarget, 2);

   hr = CoCreateInstance(&CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmMediaTypeDisp, (void**) &pmt);
   if(FAILED(hr))
   {
      MessageBox(0, "Can't instantiate convert library", "Error", 0);
      return -1;
   }

   IltmmMediaTypeDisp__put_Type(pmt, ltmmMEDIATYPE_Video);
   IltmmMultiStreamTarget_SetAcceptedMediaType(pMSTarget, 0, pmt);
   IltmmMediaTypeDisp__put_Type(pmt, ltmmMEDIATYPE_Audio);
   IltmmMultiStreamTarget_SetAcceptedMediaType(pMSTarget, 1, pmt);
   IltmmMediaTypeDisp_Release(pmt);
   pmt = NULL;

   // get the inserted media type for the first stream
   IltmmMultiStreamTarget__getAcceptedMediaType(pMSTarget, 0, &pInsertedMediaType);
   IltmmMediaTypeDisp_Release(pInsertedMediaType);
   pInsertedMediaType = NULL;

   hr = IltmmConvert__put_TargetObject(pConvert1, pMSTarget);

   // START the source conversion, so we can get the media sample format
   hr = IltmmConvert_StartConvert(pConvert1);

    //INITIALIZE pConvert2
   // get the output media sample format and put it into the source object
   IltmmMultiStreamSource__put_StreamCount(pMSSource, 2);
   hr = IltmmMultiStreamTarget__getConnectedMediaType (pMSTarget, 0, &pmt);
   IltmmMultiStreamSource_SetMediaType(pMSSource, 0, pmt);
   IltmmMediaTypeDisp_Release(pmt);
   pmt = NULL;
   IltmmMultiStreamTarget__getConnectedMediaType(pMSTarget, 1, &pmt);
   IltmmMultiStreamSource_SetMediaType(pMSSource, 1, pmt);
   IltmmMediaTypeDisp_Release(pmt);
   pmt = NULL;

   // get the inserted media type for the first stream
   IltmmMultiStreamSource__getMediaType(pMSSource, 0, &pInsertedMediaType);
   IltmmMediaTypeDisp_Release(pInsertedMediaType);
   pInsertedMediaType = NULL;

   // set the output filename
   bstr = T2OLE("C:\\Dest.avi");
   IltmmConvert__put_TargetFile(pConvert2, bstr);
   SysFreeString(bstr);
   IltmmConvert__put_SourceObject(pConvert2, pMSSource);
   // start the dest conversion
   IltmmConvert_StartConvert(pConvert2);

   // convert first file
   ConvertFile(pConvert1, pMSTarget, pMSSource, &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
   */

   IltmmMultiStreamTarget__getConnectedMediaType(pMSTarget, 0, &pmt);
   IltmmMultiStreamTarget_SetAcceptedMediaType(pMSTarget, 0, pmt);
   IltmmMediaTypeDisp_Release(pmt);
   pmt = NULL;
   IltmmMultiStreamTarget__getConnectedMediaType(pMSTarget, 1, &pmt);
   IltmmMultiStreamTarget_SetAcceptedMediaType(pMSTarget, 1, pmt);
   IltmmMediaTypeDisp_Release(pmt);
   pmt = NULL;

   // change the source file to second file
   bstr = T2OLE("C:\\Src2.avi");
   IltmmConvert__put_SourceFile(pConvert1, bstr);
   SysFreeString(bstr);
   // start converting again
   IltmmConvert_StartConvert(pConvert1);

   // convert second file
   ConvertFile(pConvert1, pMSTarget, pMSSource, &lStartHi, &lStartLo);

   // deliver end of sample to stop the conversion
   IltmmMultiStreamSource_DeliverEndOfStream(pMSSource, 0, 1000);
   IltmmMultiStreamSource_DeliverEndOfStream(pMSSource, 1, 1000);

   IltmmConvert__get_State(pConvert2, &lState);
   if (lState = ltmmConvert_State_Running)
        IltmmConvert_StopConvert(pConvert2);

   // free the source and target objects
   IltmmConvert_ResetTarget(pConvert1);
   IltmmConvert_ResetSource(pConvert2);

   if (pConvert1)
   {
      IltmmConvert_Release(pConvert1);
      pConvert1 = NULL;
   }

   if (pConvert2)
   {
      IltmmConvert_Release(pConvert2);
      pConvert2 = NULL;
   }
   if (pMSSource)
   {
      IltmmMultiStreamSource_Release(pMSSource);
      pMSSource = NULL;
   }
   if (pMSTarget)
   {
      IltmmMultiStreamTarget_Release(pMSTarget);
      pMSTarget = NULL;
   }

   CoUninitialize();
   return 0;
}

void ConvertFile(IltmmConvert* pConvert1, IltmmMultiStreamTarget* pMSTarget, IltmmMultiStreamSource* pMSSource, long* plStartHi , long *plStartLo)
{
   IltmmMediaSampleDisp* pmsSrc = NULL;
   IltmmMediaSampleDisp* pmsDst = NULL;
   long LastStartHi;
   long LastStartLo;
   long LastStopHi;
   long LastStopLo;
   long lSampleStream;
   HRESULT hr;
   long lActualDataLength;
   VARIANT vBuffer;
   VARIANT_BOOL vBool;

   LastStopHi = 0;
   LastStopLo = 0;


   do
   {
      // get the sample, allowing 10 s for the operation to complete
      hr = IltmmMultiStreamTarget_WaitForSample(pMSTarget, 1000, &lSampleStream);
      if (FAILED(hr))
         break;
      hr = IltmmMultiStreamTarget__getSample(pMSTarget, lSampleStream, 0, &pmsSrc);
      if (FAILED(hr))
         break;
      hr = IltmmMultiStreamSource__getSampleBuffer(pMSSource, lSampleStream, 2000, &pmsDst);
      if (FAILED(hr))
         break;
      // set the sample time
      IltmmMediaSampleDisp__getTime(pmsSrc, &LastStartHi, &LastStartLo, &LastStopHi, &LastStopLo);
      // get the sample time
      IltmmMediaSampleDisp_SetTime(pmsDst, *plStartHi + LastStartHi, *plStartLo + LastStartLo, *plStartHi + LastStopHi, *plStartLo + LastStopLo);

      // copy the data
      IltmmMediaSampleDisp__get_ActualDataLength(pmsSrc, &lActualDataLength);
      IltmmMediaSampleDisp__getData(pmsSrc, lActualDataLength, &vBuffer);
      IltmmMediaSampleDisp_SetData(pmsDst, lActualDataLength, vBuffer);

      // copy the other flags
      hr = IltmmMediaSampleDisp__get_Discontinuity(pmsSrc, &vBool);
      if (FAILED(hr))
         break;
      hr = IltmmMediaSampleDisp__put_Discontinuity(pmsDst, vBool);
      if (FAILED(hr))
         break;

      hr = IltmmMediaSampleDisp__get_Preroll(pmsSrc, &vBool);
      if (FAILED(hr))
         break;
      hr = IltmmMediaSampleDisp__put_Preroll(pmsDst, vBool);
      if (FAILED(hr))
         break;

      hr = IltmmMediaSampleDisp__get_SyncPoint(pmsSrc, &vBool);
      if (FAILED(hr))
         break;
      hr = IltmmMediaSampleDisp__put_SyncPoint(pmsDst, vBool);
      if (FAILED(hr))
         break;

      // release the source sample
      IltmmMediaSampleDisp_Release(pmsSrc);
      pmsSrc = NULL;
      // deliver the destination sample
      IltmmMultiStreamSource_DeliverSample(pMSSource, lSampleStream, 1000, pmsDst);
      // release the destination sample
      IltmmMediaSampleDisp_Release(pmsDst);
      pmsDst = NULL;
   }
   while (1);

   IltmmConvert_StopConvert(pConvert1);
   *plStartHi = LastStopHi;
   *plStartLo = LastStopLo;
}