1

I wrote a Windows Service Code to convert AVI to WMV file. I'm using XviD, and Windows Media 9, in a Windows Vista. The service starts converting, and stops before completing the job, with a WMENC_ENCODER_STOPPED status, but the file was not fully converted. And the resulting file stays locked to this application forever, until I stop the service. And when I do so, that resulting file is automatically deleted. Can anyone, please, help? It is important !!

EDIT: This program works constantly, executing conversion tasks. If a file fails to convert as described above, and I use the function GC.WaitForPendingFinalizers(), I still have the locking problem. But the service goes on, and pick another task. Succeeding or failing this new task, when I use GC.WaitForPendingFinalizers(), the first one is unlocked, and automatically deleted.

            public WMENC_ENCODER_STATE EncoderStatus
    {
        get { return _encoderStatus; }
        set { _encoderStatus = value; }
    }

    IWMEncFile2 File;
    IWMEncAudioSource[] SrcAud;
    IWMEncVideoSource2[] SrcVid;
    IWMEncSourceGroup2[] SrcGrp;
    WMEncoder glbEncoder = new WMEncoder();
    WMEncProfile2[] Pro = null;
    IWMEncSourceGroupCollection SrcGrpColl = null;

    public WMVEnconder(ConvertGroup[] sourceGroup, string targetFile, string profilefile)
    {
        glbEncoder.OnStateChange += new _IWMEncoderEvents_OnStateChangeEventHandler(Encoder_OnStateChange);
        glbEncoder.OnError +=new _IWMEncoderEvents_OnErrorEventHandler(Encoder_OnError);

        // Creates source group.
        SrcGrpColl = glbEncoder.SourceGroupCollection;

        int[] intProVBRModeAudio = new int[sourceGroup.Length];
        int[] intProVBRModeVideo = new int[sourceGroup.Length];
        Int32[] intProContentType = new int[sourceGroup.Length];
        Pro = new WMEncProfile2[sourceGroup.Length];
        for (int i = 0; i < Pro.Length; i++)
        {
            Pro[i] = new WMEncProfile2();
            Pro[i].LoadFromMemory(profilefile);
            intProContentType[i] = Pro[i].ContentType;
            intProVBRModeAudio[i] = (int)Pro[i].get_VBRMode(WMENC_SOURCE_TYPE.WMENC_AUDIO, 0);
            intProVBRModeVideo[i] = (int)Pro[i].get_VBRMode(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0);
        }

        SrcGrp = new IWMEncSourceGroup2[sourceGroup.Length];
        for (int i = 0; i < SrcGrp.Length; i++)
            SrcGrp[i] = (IWMEncSourceGroup2)SrcGrpColl.Add(i.ToString());

        SrcAud = new IWMEncAudioSource[sourceGroup.Length];
        SrcVid = new IWMEncVideoSource2[sourceGroup.Length];

        for (int i = 0; i < sourceGroup.Length; i++)
        {
            if (intProContentType[i] == 1)
            {
                SrcAud[i] = (WMEncoderLib.IWMEncAudioSource)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
                SrcAud[i].SetInput(sourceGroup[i].AudioFile, "", "");

                SrcAud[i].MarkIn = sourceGroup[i].AudioMarkin;
                SrcAud[i].MarkOut = sourceGroup[i].AudioMarkout;
            }
            else if (intProContentType[i] == 16)
            {
                SrcVid[i] = (WMEncoderLib.IWMEncVideoSource2)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
                SrcVid[i].SetInput(sourceGroup[i].VideoFile, "", "");

                SrcVid[i].MarkIn = sourceGroup[i].VideoMarkin;
                SrcVid[i].MarkOut = sourceGroup[i].VideoMarkout;
            }
            else if (intProContentType[i] == 17)
            {
                SrcAud[i] = (WMEncoderLib.IWMEncAudioSource)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
                SrcAud[i].SetInput(sourceGroup[i].AudioFile, "", "");

                SrcVid[i] = (WMEncoderLib.IWMEncVideoSource2)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
                SrcVid[i].SetInput(sourceGroup[i].VideoFile, "", "");

                SrcAud[i].MarkIn = sourceGroup[i].AudioMarkin;
                SrcAud[i].MarkOut = sourceGroup[i].AudioMarkout;
                SrcVid[i].MarkIn = sourceGroup[i].VideoMarkin;
                SrcVid[i].MarkOut = sourceGroup[i].VideoMarkout;
            }
            else
                throw new Exception("erro - não suporta este tipo de profile");

            SrcGrp[i].set_Profile(Pro[i]);

            if (i + 1 < sourceGroup.Length)
                SrcGrp[i].SetAutoRollover(-1, (i + 1).ToString());
        }

        File = (IWMEncFile2)glbEncoder.File;
        File.LocalFileName = targetFile;

        glbEncoder.PrepareToEncode(true);
    }
    /// <summary>
    /// Inicia os processos do codificador.
    /// </summary>
    public void Start()
    {
        glbEncoder.Start();
    }
    /// <summary>
    /// Pára os processos do codificador.
    /// </summary>
    public void Stop()
    {
        glbEncoder.Stop();
    }
    /// <summary>
    /// Elimina as configurações atuais.
    /// </summary>
    public void Reset()
    {
        glbEncoder.Reset();
    }
    /// <summary>
    /// Evento deflagrado pela mudança no estado do codificador.
    /// </summary>
    /// <param name="enumState">Enumerador indicador do estado do codificador.</param>
    private void Encoder_OnStateChange(WMEncoderLib.WMENC_ENCODER_STATE enumState)
    {
        _encoderStatus = enumState;
        string strRunState = "";
        switch (enumState)
        {
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STARTING :
                strRunState = "Encoder Starting";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING:
                strRunState = "Encoder Running";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_END_PREPROCESS:
                strRunState = "Encoder End Preprocess";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSING:
                strRunState = "Encoder Pausing";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSED:
                strRunState = "Encoder Paused";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPING:
                strRunState = "Encoder Stopping";
                break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED:
                strRunState = "Encoder Stopped";
                break;
        }
        _strEncoderStatus = strRunState;
    }
    /// <summary>
    /// Evento deflagrado pela ocorrência de um erro durante o processo de codificação.
    /// </summary>
    /// <param name="hr">Valor numérico do erro que ocorreu.</param>
    private void Encoder_OnError(int hr)
    {
        string errorReceived = "";

        switch (hr)
        {
            case -1074600792:
                errorReceived = "The starting time must be greater than zero and less than the ending time.";
                break;
            case -1074600793:
                errorReceived = "The ending time must be greater than the starting time and less than the file duration.";
                break;
            case -1074600804:
                errorReceived = "The video capture device is in use and cannot be opened.";
                break;
            case -1074600808:
                errorReceived = "The video capture driver returned an unrecoverable error.";
                break;
            case -1074600809:
                errorReceived = "The video capture device did not start.";
                break;
            case -1074600813:
                errorReceived = "The video capture window was not created.";
                break;
            case -1074600820:
                errorReceived = "The specified operation is not allowed when the file is being archived.";
                break;
            case -1074600825:
                errorReceived = "The archive file name is not properly specified.";
                break;
            case -1074600831:
                errorReceived = "The specified operation is not allowed when the encoder engine is not running.";
                break;
            case -1074600833:
                errorReceived = "Inverse telecine cannot be specified when the frame rate does not equal 30 frames per second.";
                break;
            case -1074600834:
                errorReceived = "Internal problems are preventing the preview or postview.";
                break;
            case -1074600835:
                errorReceived = "One or more required codecs cannot be found.";
                break;
            case -1074600840:
                errorReceived = "The display size or color setting has changed since the encoding session was defined.";
                break;
        }

        try
        {
            if (Directory.Exists(@"C:\MediaDNA_V2\Data\Conversion\Exception"))
            {
                MediaDNAException mdnaException = new MediaDNAException(Modulo.CONVERSION, 0, "C_110018", TipoErro.INFORMACAO, new Exception(errorReceived),
                    ErrorMessageConstants.C_110018, new object[] { hr.ToString("X") });
                ExceptionManager.RegisterException(mdnaException, @"C:\MediaDNA_V2\Data\Conversion\Exception");
            }
        }
        catch { }
    }

    #region IDisposable Members
    /// <summary> Release everything. </summary>
    public void Dispose()
    {
        glbEncoder.Stop();
        glbEncoder.Reset();
        GC.SuppressFinalize(this);
        CloseInterfaces();
    }
    #endregion

    /// <summary>
    /// Fecha as interfaces utilizadas pelo codificador.
    /// Obs: O processador precisa estar "STOPPED" para executar este processo.
    /// </summary>
    private void CloseInterfaces()
    {
        if (glbEncoder != null)
        {
            if (File != null)
                Marshal.FinalReleaseComObject(File);
            if (Pro != null)
            {
                for (int i = 0; i < Pro.Length; i++)
                    Marshal.FinalReleaseComObject(Pro[i]);

                Pro = null;
            }
            if (SrcVid != null)
            {
                for (int i = 0; i < SrcVid.Length; i++)
                    Marshal.FinalReleaseComObject(SrcVid[i]);

                SrcVid = null;
            }
            if (SrcAud != null)
            {
                for (int i = 0; i < SrcAud.Length; i++)
                    Marshal.FinalReleaseComObject(SrcAud[i]);

                SrcAud = null;
            }
            if (SrcGrpColl != null)
                Marshal.FinalReleaseComObject(SrcGrpColl);
            if (SrcGrpColl != null)
                Marshal.FinalReleaseComObject(SrcGrpColl);
            if (glbEncoder != null)
                Marshal.FinalReleaseComObject(glbEncoder);
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
    }

1 Answers1

1

I attached my function which I converted wav file to wma.
Make sure that you do encoder.Stop(); and encoder.Reset(); and off-course release all your com object.

I'm pretty sure that once you will released your COM object your issue will be fixed.

    // Create a WMEncoder object.
    WMEncoder encoder = new WMEncoder();

    // Retrieve the source group collection.
    IWMEncSourceGroupCollection srcGrpColl = encoder.SourceGroupCollection;

    // Add a source group to the collection.
    IWMEncSourceGroup srcGrp = srcGrpColl.Add("SG_1");

    // Add a video and audio source to the source group.
    IWMEncSource srcAud = srcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
    srcAud.SetInput(wavFileName, "", "");

    // Specify a file object in which to save encoded content.
    IWMEncFile file = encoder.File;
    file.LocalFileName = wmaFileName;

    // Create a profile collection object from the WMEncoder object.
    encoder.ProfileCollection.ProfileDirectory = 
        string.Format("{0}Profiles", Request.PhysicalApplicationPath);
    encoder.ProfileCollection.Refresh();
    IWMEncProfileCollection proColl = encoder.ProfileCollection;

    // Create a profile object
    IEnumerator profEnum = proColl.GetEnumerator();
    IWMEncProfile profile = null; ;
    IWMEncProfile2 newProfile = null;
    while (profEnum.MoveNext())
    {
        profile = (IWMEncProfile)profEnum.Current;
        if (profile.Name == "WavToWma")
        {
            // Load profile
            newProfile = new WMEncProfile2();
            newProfile.LoadFromIWMProfile(profile);

            // Specify this profile object as the profile to use in source group.
            srcGrp.set_Profile(newProfile);
        }
    }

    // Start the encoding process.
    // Wait until the encoding process stops before exiting the application.
    encoder.PrepareToEncode(true);
    encoder.Start();
    while (encoder.RunState != WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)
    {
        Thread.Sleep(500);
    }
    encoder.Stop();
    encoder.Reset();

    try
    {
        #region Release com objects
        if (file != null)
            Marshal.FinalReleaseComObject(file);
        if (profile != null)
            Marshal.FinalReleaseComObject(profile);
        if (newProfile != null)
            Marshal.FinalReleaseComObject(newProfile);
        if (srcAud != null)
            Marshal.FinalReleaseComObject(srcAud);
        if (srcGrp != null)
            Marshal.FinalReleaseComObject(srcGrp);
        if (srcGrpColl != null)
            Marshal.FinalReleaseComObject(srcGrpColl);
        if (proColl != null)
            Marshal.FinalReleaseComObject(proColl);
        if (encoder != null)
            Marshal.FinalReleaseComObject(encoder);
        // GC collect is explicitly called because of a memory leak issue of WMEncoder.
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        #endregion
    }
    catch { }
}
Dor Cohen
  • 16,769
  • 23
  • 93
  • 161
  • Hi man, thanks for your answer !! But, unfortunately, I was aready releasing all COM interfaces, and calling GC, and I checked my code looking yours, but I still get the same error. Any other clue!? Would it help, if I attach here my code? – Renato Kovarish Nov 06 '12 at 16:05
  • Dor Cohen, did you see my code? If you need any other piece of my code, please, let me know. Or even if you have any available time, and feel comfortable to join me on skype, I'll be glad to share my work. – Renato Kovarish Nov 08 '12 at 12:49