読者です 読者をやめる 読者になる 読者になる

S.F. Page

Programming,Music,etc...

音声ファイルから動画ファイルを生成する(48) – AVXとアラインメント

AVXで勉強がてら実装してみようと思っているのは以下の部分である。

  // テクスチャをメディアバッファに書き込む
  void video_writer::set_texture_to_sample(ID3D11DeviceContext1* context, ID3D11Texture2D* texture)
  {

    // タイムスタンプの設定
    CHK(sample_->SetSampleTime(video_sample_time_));

    // 書き込み先バッファのロック
    unsigned char *pbBuffer = nullptr;
    CHK(buffer_->Lock(&pbBuffer, nullptr, nullptr));

    // 読み込みテクスチャをマップ
    D3D11_MAPPED_SUBRESOURCE mapped;
    CHK(context->Map(texture, 0, D3D11_MAP_READ, 0, &mapped));

    //CHK(MFCopyImage(pbBuffer, width_ * 4, reinterpret_cast<BYTE*>(mapped.pData), mapped.RowPitch, width_ * 4, height_));

    DWORD *dest = (DWORD*) pbBuffer;
    const UINT pitch = mapped.RowPitch / sizeof(DWORD);
    DWORD *src = (DWORD*) mapped.pData + (height_ - 1) * pitch;

    for (UINT i = 0; i < height_; ++i){
      for (UINT j = 0; j < width_; ++j){
        *dest++ = *src++;
      }
      src -= pitch * 2;
    }

    // 書き込み先バッファのアンロック
    CHK(buffer_->Unlock());
    // テクスチャをアンマップ
    context->Unmap(texture, 0);
    video_sample_time_ += hnsSampleDuration;
  }

2つのforループの部分をXbyakで書き換えるつもりなのである。buffer_というのがIMFMediaBufferで、ID3D11Texture2Dをmapしてポインタを得て読みだして、IMFMediaBufferをlockしてポインタを得てそのポインタに書き込むのである。

このロックしたりマップしたりするポインタのアラインメントが16byteになっているのであれば実装が比較的簡単となる。そうでなければアラインメントをそろえるための前処理が必要になりコードが若干複雑となる。IMFMediaBufferはMFCreateAlignedMemoryBufferでアラインメントされたものを得ることができるし、ID3D11Texture2DもDirect3D10以降は16バイトでアラインメントされていることが今日わかったので、AVXの128ビットSIMDであればアラインメントが揃っているという前提でコードを書くことができる。あとはこのあたりの資料をみながらぼちぼち実装していくだけである。