如何使用 ASF Writer 更快地压缩 WMV? 有什么提示吗?

发布于 2024-07-18 08:32:03 字数 4340 浏览 2 评论 0原文

我正在使用 ASF Writer 将原始 AVI 文件压缩为 WMV。 我非常需要加快压缩速度。 有任何提示和信息吗? 如何实现这一目标的最佳实践? 降低/降低索引器影响? 有任何隐藏压缩参数吗?

这些文件仅包含 RGB/24 位格式的视频,视频流的压缩级别在 200kbps 到 2000kbps 之间。

任何配置提示(使用 C++、C#、Delphi 等)

这是配置 WMV 编写器的代码部分(使用 DSPack)。

function CreateWMVWriter(VideoQuality, AudioQuality: Cardinal; videoInfo: PVideoInfoHeader; audioInfo: PWaveFormatEx; hasAudio: Boolean): IBaseFilter;
const
  PROFILE_NAME = 'WMV AutoProfile';
  // BUFFER_WINDOW = $FFFFFFFF;  // auto buffer
  BUFFER_WINDOW = 1000;  // 1 second
  MAX_KEY_FRAME_SPACING = 10000000; // 1 seconds
var
  configWriter : IConfigAsfWriter;
  profileManager : IWMProfileManager;
  profile : IWMProfile;
  stream : IWMStreamConfig;
  mediaProps : IWMMediaProps;
  vmediaProps : IWMVideoMediaProps;
  pmt : PWMMediaType;
  msize : Cardinal;
  vih : PVideoInfoHeader;
  wfe: PWaveFormatEx;
  hr : HRESULT;
  videoBitRate, audioBitRate: Cardinal;
  width, height: Integer;
begin
  videoBitRate := VideoQuality * 1000; // kbits
  // create the profile
  CheckDSError(WMCreateProfileManager(profileManager));
  CheckDSError(profileManager.CreateEmptyProfile(WMT_VER_9_0, profile));
  CheckDSError(profile.SetName(StringToOleStr(PROFILE_NAME)));
  CheckDSError(profile.SetDescription(StringToOleStr(PROFILE_NAME)));
  CheckDSError(profile.CreateNewStream(WMMEDIATYPE_Video, stream));
  CheckDSError(stream.SetStreamName(StringToOleStr('Video')));
  CheckDSError(stream.SetBitrate(videoBitRate));
  CheckDSError(stream.SetBufferWindow(BUFFER_WINDOW));
  // config video media type
  stream.QueryInterface(IID_IWMMediaProps, mediaProps);
  CheckDSError(mediaProps.GetMediaType(nil, msize));
  GetMem(pmt, msize);
  CheckDSError(mediaProps.GetMediaType(pmt, msize));
  with pmt^ do
  begin
    majortype := WMMEDIATYPE_Video;
    subtype := WMMEDIASUBTYPE_WMV3;
    bFixedSizeSamples := True;
    bTemporalCompression := True;
    pUnk := nil;
    vih := PVideoInfoHeader(pbFormat);
    // copy video info header (the same as with the original - copy: rcSource, rcTarget, AvgTimePerFrame, biWidth, biHeight)
    CopyMemory(vih, videoInfo, SizeOf(TVideoInfoHeader));
    // set bit rate at the same value
    vih.dwBitRate := videoBitRate;
    // set new compression ('WMV3')
    vih.bmiHeader.biCompression := MAKEFOURCC('W', 'M', 'V', '3');
  end;
  CheckDSError(mediaProps.SetMediaType(pmt));
  FreeMem(pmt, msize);
  // set media props
  stream.QueryInterface(IID_IWMVideoMediaProps, vmediaProps);
  CheckDSError(vmediaProps.SetQuality(100));
  CheckDSError(vmediaProps.SetMaxKeyFrameSpacing(0));
  // CheckDSError(vmediaProps.SetMaxKeyFrameSpacing(MAX_KEY_FRAME_SPACING));
  // add video stream
  CheckDSError(profile.AddStream(stream));
  // add audio stream (if needed)
  if hasAudio then
  begin
    CheckDSError(profile.CreateNewStream(WMMEDIATYPE_Audio, stream));
    CheckDSError(stream.SetStreamName(StringToOleStr('Audio')));
    audioBitRate := audioInfo.nSamplesPerSec * audioInfo.nChannels * audioInfo.wBitsPerSample;
    CheckDSError(stream.SetBitrate(audioBitRate));
    CheckDSError(stream.SetBufferWindow(BUFFER_WINDOW)); // auto
    // config video media type
    stream.QueryInterface(IID_IWMMediaProps, mediaProps);
    CheckDSError(mediaProps.GetMediaType(nil, msize));
    GetMem(pmt, msize);
    hr := mediaProps.GetMediaType(pmt, msize);
    with pmt^ do
    begin
      // uncompressed audio
      majortype := WMMEDIATYPE_Audio;
      subtype := WMMEDIASUBTYPE_PCM;
      formattype := WMFORMAT_WaveFormatEx;
      cbFormat := sizeof(TWaveFormatEx);
      bFixedSizeSamples := True;
      bTemporalCompression := False;
      lSampleSize := audioInfo.nChannels * audioInfo.wBitsPerSample div 8;
      pUnk := nil;
      wfe := PWaveFormatEx(pbFormat);
      // copy video info header (the same as with the original)
      CopyMemory(wfe, audioInfo, SizeOf(TWaveFormatEx));
    end;
    CheckDSError(mediaProps.SetMediaType(pmt));
    FreeMem(pmt, msize);
    // add video stream
    CheckDSError(profile.AddStream(stream));
  end;

  // create the writer
  Result := AddFilterGUID(CLSID_WMAsfWriter, 'WmvWriter');

  // config the writer
  configWriter := Result as IConfigAsfWriter;
  CheckDSError(configWriter.SetIndexMode(True));
  CheckDSError(configWriter.ConfigureFilterUsingProfile(profile));
end;

I'm compressing raw AVI files to WMV using the ASF Writer.
I'm in a big need to make the compression faster.
There are any hints & best practicevs on how to achieve this ? Drop/lower the indexer impact ? Any hidden compression parameters ?

The files contains just video in RGB/24bits format and the compression level for the video stream is between 200kbps and 2000kbps.

Any configuration hints (using C++, C#, Delphi, etc)

Here is the the part of the code (using DSPack) that configure the WMV writer.

function CreateWMVWriter(VideoQuality, AudioQuality: Cardinal; videoInfo: PVideoInfoHeader; audioInfo: PWaveFormatEx; hasAudio: Boolean): IBaseFilter;
const
  PROFILE_NAME = 'WMV AutoProfile';
  // BUFFER_WINDOW = $FFFFFFFF;  // auto buffer
  BUFFER_WINDOW = 1000;  // 1 second
  MAX_KEY_FRAME_SPACING = 10000000; // 1 seconds
var
  configWriter : IConfigAsfWriter;
  profileManager : IWMProfileManager;
  profile : IWMProfile;
  stream : IWMStreamConfig;
  mediaProps : IWMMediaProps;
  vmediaProps : IWMVideoMediaProps;
  pmt : PWMMediaType;
  msize : Cardinal;
  vih : PVideoInfoHeader;
  wfe: PWaveFormatEx;
  hr : HRESULT;
  videoBitRate, audioBitRate: Cardinal;
  width, height: Integer;
begin
  videoBitRate := VideoQuality * 1000; // kbits
  // create the profile
  CheckDSError(WMCreateProfileManager(profileManager));
  CheckDSError(profileManager.CreateEmptyProfile(WMT_VER_9_0, profile));
  CheckDSError(profile.SetName(StringToOleStr(PROFILE_NAME)));
  CheckDSError(profile.SetDescription(StringToOleStr(PROFILE_NAME)));
  CheckDSError(profile.CreateNewStream(WMMEDIATYPE_Video, stream));
  CheckDSError(stream.SetStreamName(StringToOleStr('Video')));
  CheckDSError(stream.SetBitrate(videoBitRate));
  CheckDSError(stream.SetBufferWindow(BUFFER_WINDOW));
  // config video media type
  stream.QueryInterface(IID_IWMMediaProps, mediaProps);
  CheckDSError(mediaProps.GetMediaType(nil, msize));
  GetMem(pmt, msize);
  CheckDSError(mediaProps.GetMediaType(pmt, msize));
  with pmt^ do
  begin
    majortype := WMMEDIATYPE_Video;
    subtype := WMMEDIASUBTYPE_WMV3;
    bFixedSizeSamples := True;
    bTemporalCompression := True;
    pUnk := nil;
    vih := PVideoInfoHeader(pbFormat);
    // copy video info header (the same as with the original - copy: rcSource, rcTarget, AvgTimePerFrame, biWidth, biHeight)
    CopyMemory(vih, videoInfo, SizeOf(TVideoInfoHeader));
    // set bit rate at the same value
    vih.dwBitRate := videoBitRate;
    // set new compression ('WMV3')
    vih.bmiHeader.biCompression := MAKEFOURCC('W', 'M', 'V', '3');
  end;
  CheckDSError(mediaProps.SetMediaType(pmt));
  FreeMem(pmt, msize);
  // set media props
  stream.QueryInterface(IID_IWMVideoMediaProps, vmediaProps);
  CheckDSError(vmediaProps.SetQuality(100));
  CheckDSError(vmediaProps.SetMaxKeyFrameSpacing(0));
  // CheckDSError(vmediaProps.SetMaxKeyFrameSpacing(MAX_KEY_FRAME_SPACING));
  // add video stream
  CheckDSError(profile.AddStream(stream));
  // add audio stream (if needed)
  if hasAudio then
  begin
    CheckDSError(profile.CreateNewStream(WMMEDIATYPE_Audio, stream));
    CheckDSError(stream.SetStreamName(StringToOleStr('Audio')));
    audioBitRate := audioInfo.nSamplesPerSec * audioInfo.nChannels * audioInfo.wBitsPerSample;
    CheckDSError(stream.SetBitrate(audioBitRate));
    CheckDSError(stream.SetBufferWindow(BUFFER_WINDOW)); // auto
    // config video media type
    stream.QueryInterface(IID_IWMMediaProps, mediaProps);
    CheckDSError(mediaProps.GetMediaType(nil, msize));
    GetMem(pmt, msize);
    hr := mediaProps.GetMediaType(pmt, msize);
    with pmt^ do
    begin
      // uncompressed audio
      majortype := WMMEDIATYPE_Audio;
      subtype := WMMEDIASUBTYPE_PCM;
      formattype := WMFORMAT_WaveFormatEx;
      cbFormat := sizeof(TWaveFormatEx);
      bFixedSizeSamples := True;
      bTemporalCompression := False;
      lSampleSize := audioInfo.nChannels * audioInfo.wBitsPerSample div 8;
      pUnk := nil;
      wfe := PWaveFormatEx(pbFormat);
      // copy video info header (the same as with the original)
      CopyMemory(wfe, audioInfo, SizeOf(TWaveFormatEx));
    end;
    CheckDSError(mediaProps.SetMediaType(pmt));
    FreeMem(pmt, msize);
    // add video stream
    CheckDSError(profile.AddStream(stream));
  end;

  // create the writer
  Result := AddFilterGUID(CLSID_WMAsfWriter, 'WmvWriter');

  // config the writer
  configWriter := Result as IConfigAsfWriter;
  CheckDSError(configWriter.SetIndexMode(True));
  CheckDSError(configWriter.ConfigureFilterUsingProfile(profile));
end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雪落纷纷 2024-07-25 08:32:03

我对此确实没有太多经验,但根据其他地方发布的内容,尝试设置 WMMEDIASUBTYPE_WVC1 而不是 WMMEDIASUBTYPE_WVC3。 信息是从此处收集的。

其他一些可能有用的链接:此处这里

I really don't have a lot of experience with this, but from what has been posted elsewhere, try setting WMMEDIASUBTYPE_WVC1 instead of WMMEDIASUBTYPE_WVC3. Information was gleaned from here.

Some other links that might be helpful: here and here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文