我编写了一个 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();
}
}