Menyinkronkan Perintah DVD

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan Audio/Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Audio/Video Capture di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Perintah DVD tidak selalu selesai secara instan. Untuk alasan ini, beberapa metode dalam IDvdControl2 tidak sinkron. Ini termasuk metode pemutaran, seperti PlayTitle, dan metode navigasi menu, seperti ShowMenu dan ReturnFromSubmenu. Metode asinkron segera kembali, tanpa menunggu perintah selesai. Setelah metode kembali, peristiwa lain dapat mencegah perintah selesai, bahkan jika metode berhasil. DirectShow menyediakan beberapa opsi untuk menyinkronkan perintah, mulai dari tidak ada sinkronisasi hingga sinkronisasi penuh menggunakan peristiwa grafik filter.

Semua metode asinkron memiliki parameter dwFlags dan parameter ppCmd . Parameter dwFlags menentukan perilaku sinkronisasi, dan parameter ppCmd mengembalikan penunjuk ke objek sinkronisasi opsional. Perilaku yang berbeda dihasilkan tergantung pada nilai apa yang Anda berikan untuk parameter ini.

Tidak Ada Sinkronisasi

Untuk aplikasi pemutaran DVD dasar, opsi terbaik mungkin hanya mengabaikan masalah sinkronisasi. Terkadang perintah mungkin gagal atau UI mungkin sedikit tertinggal ketika diperbarui, tetapi kesalahan ini akan berada pada urutan pecahan detik.

Untuk mengeluarkan perintah tanpa sinkronisasi, atur bendera DVD_CMD_FLAG_None di parameter dwFlags dan atur parameter ppCmd ke NULL:

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, NULL);

Pemblokiran

Jika Anda mengatur bendera EC_DVD_CMD_FLAG_Block di parameter dwFlags , metode akan memblokir hingga perintah selesai:

hr = pDVDControl2->PlayTitle(uTitle, EC_DVD_CMD_FLAG_Block, NULL);

Akibatnya, bendera ini mengubah metode asinkron menjadi metode sinkron. Kelemahannya adalah UI Anda memblokir jika Anda memanggil metode dari utas aplikasi.

Objek Sinkronisasi

Semua metode asinkron dapat mengembalikan objek sinkronisasi, yang dapat Anda gunakan untuk menunggu perintah dimulai atau berakhir. Untuk mendapatkan objek ini, berikan alamat penunjuk IDvdCmd dalam parameter ppCmd :

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, &pCmdObj);

Jika metode berhasil, metode mengembalikan objek IDvdCmd baru. Metode IDvdCmd::WaitForStart memblokir hingga perintah dimulai, dan metode IDvdCmd::WaitForEnd memblokir hingga perintah berakhir. Nilai yang dikembalikan menunjukkan status perintah.

Kode berikut secara fungsional setara dengan pengaturan bendera EC_DVD_CMD_FLAG_Block, yang diperlihatkan sebelumnya.

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, &pCmdObj);
if (SUCCEEDED(hr))
{
    // Use pCmdObj to wait for the command to complete.
    hr = pCmdObj->WaitToEnd();
    pCmdObj->Release();
}

Dalam hal ini, metode PlayTitle tidak memblokir, tetapi aplikasi memblokir dengan memanggil WaitForEnd.

Peristiwa Status Perintah

Jika Anda mengatur bendera DVD_CMD_FLAG_SendEvents di parameter dwFlags , DVD Navigator mengirimkan peristiwa EC_DVD_CMD_START saat perintah dimulai dan peristiwa EC_DVD_CMD_END saat perintah berakhir.

Parameter lParam2 peristiwa adalah nilai pengembalian HRESULT untuk perintah . Parameter lParam1 peristiwa menyediakan cara mendapatkan objek sinkronisasi untuk perintah . Jika Anda meneruskan lParam1 ke metode IDvdInfo2::GetCmdFromEvent , metode mengembalikan pointer ke antarmuka IDvdCmd objek sinkronisasi. Anda dapat menggunakan antarmuka ini untuk menunggu penyelesaian perintah, seperti yang dijelaskan sebelumnya. Namun, jika Anda melewati NULL untuk parameter ppCmd dalam metode IDvdControl2 asli, Navigator DVD tidak membuat objek sinkronisasi, dan GetCmdFromEvent mengembalikan E_FAIL.

Kode berikut menunjukkan cara menggunakan peristiwa status perintah tanpa objek sinkronisasi.

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_SendEvents, NULL);

// In your event handling code:
switch (lEvent)
{
   case EC_DVD_CMD_END:
       HRESULT hr2 = (HRESULT)lParam2;
       /* ... */ 
       break;
}

Perhatikan bahwa tanpa objek sinkronisasi, Anda tidak dapat mengetahui perintah mana yang terkait dengan peristiwa tersebut. Kode berikut menunjukkan cara menggunakan peristiwa dengan objek sinkronisasi. Idenya adalah untuk menyimpan objek sinkronisasi dalam daftar lalu membandingkan penunjuk objek saat Anda mendapatkan peristiwa EC_DVD_CMD_START atau EC_DVD_CMD_END .

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_SendEvents, &pCmdObj);
if (SUCCEEDED(hr)) 
{
    // Store pCmdObj in a list of pending commands.
}

// In your event handling code:
switch (lEvent)
{
case EC_DVD_CMD_END:
   {
       IDvdCmd *pObj = NULL;
       hr = pDvdInfo2->GetCmdFromEvent(lParam, &pObj);
       if (SUCCEEDED(hr)) 
       {
           // Find this object in your list by comparing IUnknown
           // pointers. Assume the following function is defined in 
           // your application:
           IDvdCmd *pPendingObj = GetPendingCommandFromList(pObj); 
           if (pPendingObj)
           {
               // Update UI accordingly (not shown). 
               pPendingObj->Release();
           }
           pObj->Release();
       }
    }
    break;
} 

Menyiram Buffer DVD Navigator

Selama pemutaran, DVD Navigator menyangga data video. Jumlah data yang di-buffer bervariasi. Ketika NAVIGATOR DVD beralih ke bagian video baru, data yang sudah ada di alur tidak hilang, sehingga transisinya mulus. Secara default, ketika DVD Navigator mengeluarkan perintah, DVD Navigator tidak menghapus data yang sudah ada di alur. Akibatnya, mungkin ada beberapa latensi sebelum Anda dapat melihat efek perintah, tergantung pada berapa banyak data yang di-buffer. Untuk meningkatkan responsivitas, Anda dapat memaksa Navigator DVD untuk membersihkan dengan mengatur bendera DVD_CMD_FLAG_Flush.

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_Flush, NULL);

Bendera ini dapat dikombinasikan dengan salah satu bendera yang dijelaskan sebelumnya, menggunakan bitwise OR. Efek samping dari pembersihan adalah bahwa beberapa video mungkin hilang, jadi jangan gunakan bendera ini jika Anda perlu menjamin tidak ada celah dalam video.

Aplikasi DVD