如何强制写入 IWMSinkWriter 上残留的优秀样本?

How can I force outstanding samples lingering on an IWMSinkWriter to be written?

我有一个 IWMSinkWriter 对象正在接收来自 WMA 编码器转换的压缩样本。

我想执行一个 "Drain" 操作,在这个操作中,仍然留在接收器写入器上的输入样本不会被丢弃(因为它当前发生在 IWMSinkWriter::Flush() 操作中)而是提交到磁盘不关闭目标文件,类似于在 C 文件上调用 fflush()

我认为我传递给 IWMSinkWriter 的样本最终会被写入磁盘,所以我尝试像这样实现这个 "Drain" 功能:

void WmaWriterBox::HandleCommand(DrainCommand^ command) {
   HRESULT hRes;
   BASE::HandleCommand(command);
   MF_SINK_WRITER_STATISTICS statistics;
   statistics.cb = sizeof(statistics);
   // spin-wait until the pending samples are processed
   while( true ) {
      COM_CALL(_pWriter->GetStatistics(0, &statistics));
      if( !statistics.dwNumOutstandingSinkSampleRequests )
         break;
      Thread::Sleep(10);
   }
}

不幸的是,未完成的样本计数从未下降到零,所以我进入了无限循环。

有什么方法可以实现这个 "write-pending-data-to-disk" 功能吗?

你应该使用 IMFSinkWriter::Finalize:

Call this method after you send all of the input samples to the sink writer. The method performs any operations needed to create the final output from the media sink.

该方法在内部对流结束命令进行排队并开始完成输出。预计将包括待定样本。

与 MFT 不同,文件写入不应该在产生尽可能多的输出流方面实现耗尽,然后返回准备好接受进一步的输入。大多数文件格式的结构方式是文件在完全确定之前不可读,潜在的耗尽将无法确保当前输入的数据写入文件并且文件可读。在大多数情况下,您有责任在任何写入的数据可回放之前完成写入。

因此,你没有方法,甚至没有挑战来处理未完成的数据:你只是一直写下去,最后完成。接收器正在以一些分别方便的方式写入,它唯一的合同责任是在您完全完成写入后交付良好的输出文件。请注意,特别是对于 ASF 格式,要求有所放松,如果未正确完成,文件在某种程度上可能仍然可读。

Flushing相反,丢弃未完成的数据:

For each stream that is flushed, the sink writer drops all pending samples...