1

我编写了一个 Windows 服务代码来将 AVI 转换为 WMV 文件。我在 Windows Vista 中使用 XviD 和 Windows Media 9。服务开始转换,并在完成作业之前停止,状态为 WMENC_ENCODER_STOPPED,但文件未完全转换。并且生成的文件永远锁定到这个应用程序,直到我停止服务。当我这样做时,生成的文件会被自动删除。有人可以帮忙吗?这很重要 !!

编辑:该程序不断工作,执行转换任务。如果文件无法按上述方式转换,并且我使用函数 GC.WaitForPendingFinalizers(),我仍然有锁定问题。但服务继续,并选择另一个任务。成功或失败这个新任务,当我使用 GC.WaitForPendingFinalizers() 时,第一个被解锁并自动删除。

            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();
        }
    }
4

1 回答 1

1

我附加了我将 wav 文件转换为 wma 的函数。
确保你这样做encoder.Stop();并且encoder.Reset();偏离路线释放你所有的 com 对象。

我很确定一旦你发布了你的 COM 对象,你的问题就会得到解决。

    // 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 { }
}
于 2012-11-06T15:35:44.143 回答