Bagikan melalui


Menghasilkan Sampel Aliran dari Objek Data ASF yang Ada

Objek pemisah ASF adalah komponen lapisan WMContainer yang mengurai Objek Data ASF dari file Advanced Systems Format (ASF).

Sebelum meneruskan paket data ke pemisah, aplikasi harus menginisialisasi, mengonfigurasi, dan memilih aliran pada pemisah untuk menyiapkannya untuk proses penguraian. Untuk informasi, lihat Membuat Objek Pemisah ASF dan Mengonfigurasi Objek Pemisah ASF.

Metode yang diperlukan untuk mengurai Objek Data ASF adalah:

Menemukan Offset Data

Sebelum memulai proses penguraian, aplikasi harus menemukan Objek Data dalam file ASF. Ada dua cara untuk mendapatkan offset Objek Data dari awal file:

  • Sebelum menginisialisasi objek ContentInfo, Anda dapat memanggil metode IMFASFContentInfo::GetHeaderSize . Metode ini memerlukan buffer yang berisi 30 byte pertama header ASF. Ini mengembalikan ukuran seluruh header yang menunjukkan offset ke paket data pertama. Nilai ini juga menyertakan ukuran header Objek Data 50 byte.

  • Setelah menginisialisasi objek ContentInfo, Anda bisa mendapatkan deskriptor presentasi dengan memanggil IMFASFContentInfo::GeneratePresentationDescriptor, lalu mengkueri deskriptor presentasi untuk atribut MF_PD_ASF_DATA_START_OFFSET . Nilai atribut ini adalah ukuran header.

    Catatan

    Atribut MF_PD_ASF_DATA_LENGTH pada deskriptor presentasi menentukan panjang Objek Data ASF.

     

Dalam kedua kasus, nilai yang dikembalikan adalah ukuran Objek Header ditambah ukuran bagian header Objek Data. Oleh karena itu, nilai yang dihasilkan adalah offset ke awal paket data di Objek Data ASF. Saat Anda mulai mengirim data ke pemisah, data harus dimulai pada offset ini dari awal file ASF.

Nilai offset diteruskan sebagai parameter ke ParseData yang memulai proses penguraian.

Objek Data dibagi menjadi paket data. Setiap paket data berisi header paket data yang menyediakan informasi penguraian paket dan data payload—data media digital yang sebenarnya. Dalam skenario pencarian, aplikasi mungkin ingin pemisah mulai mengurai pada paket data tertentu. Untuk melakukan ini, Anda dapat menggunakan Pengindeks ASF digunakan untuk mengambil offset. Pengindeks mengembalikan nilai offset yang dimulai pada batas paket. Jika Anda tidak menggunakan pengindeks, pastikan bahwa offset dimulai di awal header paket data. Jika offset yang tidak valid diteruskan ke pemisah, seperti nilai tidak menunjuk ke batas paket, panggilan ParseHeader dan GetNextSample berhasil tetapi GetNextSample tidak mengambil sampel apa pun dan NULL diterima dalam parameter pSample .

Jika pemisah dikonfigurasi untuk mengurai ke arah terbalik, maka pemisah selalu mulai mengurai di akhir buffer media yang diteruskan ke ParseData. Oleh karena itu, untuk penguraian terbalik dalam panggilan ke ParseData, berikan offset dalam parameter cbLength , yang menentukan panjang data dan mengatur cbBufferOffset ke nol.

Menghasilkan Sampel untuk Paket Data ASF

Aplikasi memulai proses penguraian dengan meneruskan paket data ke pemisah. Input ke pemisah adalah serangkaian buffer media yang berisi seluruh atau fragmen Objek Data. Output dari pemisah adalah serangkaian sampel media yang berisi data paket.

Untuk meneruskan data input ke pemisah, buat buffer media dan isi dengan data dari bagian Objek Data dari file ASF. (Untuk informasi selengkapnya tentang buffer media, lihat Buffer Media.) Kemudian, teruskan buffer media ke metode IMFASFSplitter::P arseData . Anda juga dapat menentukan:

  • Offset ke dalam buffer di mana pemisah harus mulai mengurai. Jika offset adalah nol, penguraian dimulai pada awal buffer. Untuk informasi tentang mengatur offset data, lihat bagian "Menemukan Offset Data" dalam topik ini.
  • Jumlah data yang akan diurai. Jika nilai ini nol, pemisah mengurai hingga mencapai akhir buffer, seperti yang ditentukan oleh metode IMFMediaBuffer::GetCurrentLength .

Pemisah menghasilkan sampel media dengan mereferensikan data di buffer media. Klien dapat mengambil sampel output dengan memanggil IMFASFSplitter::GetNextSample dalam perulangan hingga tidak ada lagi data yang akan diurai. Jika GetNextSample mengembalikan bendera ASF_STATUSFLAGS_INCOMPLETE di parameter pdwStatusFlags , itu berarti ada lebih banyak sampel untuk diambil, dan aplikasi dapat memanggil GetNextSample lagi. Jika tidak, panggil ParseData untuk meneruskan lebih banyak data ke pemisah. Untuk sampel yang dihasilkan, pemisah menetapkan informasi berikut:

  • Pemisah mengatur stempel waktu pada semua sampel yang dihasilkannya. Waktu sampel mewakili waktu presentasi dan tidak menyertakan waktu pra-pendaftaran. Aplikasi dapat memanggil IMFSample::GetSampleTime untuk mendapatkan waktu presentasi, dalam unit 100 nanodetik.
  • Jika jeda terjadi selama pembuatan sampel, pemisah mengatur atribut MFSampleExtension_Discontinuity pada sampel pertama setelah penghentian. Penghentian biasanya disebabkan oleh paket yang dihilangkan pada koneksi jaringan, data file yang rusak, atau peralihan pemisah dari satu aliran sumber ke aliran sumber lainnya.
  • Untuk video, pemisah memeriksa apakah sampel berisi bingkai kunci. Jika ya, pemisah mengatur atribut MFSampleExtension_CleanPoint pada sampel.

Jika pemisah mengurai paket data yang diterima dari server media, ada kemungkinan bahwa panjang paket bervariasi. Dalam hal ini, klien harus memanggil ParseData untuk setiap paket dan mengatur atribut MFASFSPLITTER_PACKET_BOUNDARY pada setiap buffer yang dikirim ke pemisah. Atribut ini menunjukkan kepada pemisah apakah buffer media berisi awal paket ASF. Atur atribut ke TRUE jika buffer berisi awal paket baru. Jika buffer berisi kelanjutan paket sebelumnya, atur atribut ke FALSE. Buffer tidak dapat menjangkau beberapa paket.

Sebelum meneruskan buffer media baru ke pemisah, aplikasi harus memanggil IMFASFSplitter::Flush. Metode ini mengatur ulang pemisah dan menghapus bingkai parsial apa pun yang menunggu untuk diselesaikan. Ini berguna dalam skenario pencarian di mana offset berada di lokasi yang berbeda.

Contoh

Contoh kode berikut menunjukkan cara mengurai paket data. Contoh ini mengurai dari awal Objek Data ke akhir aliran dan menampilkan informasi tentang sampel yang berisi bingkai kunci. Untuk contoh lengkap yang menggunakan kode ini, lihat Tutorial: Membaca File ASF.

// Parse the video stream and display information about the video samples.
//
// The current read position of the byte stream must be at the start of the ASF
// Data Object.

HRESULT DisplayKeyFrames(IMFByteStream *pStream, IMFASFSplitter *pSplitter)
{
    const DWORD cbReadSize = 2048;  // Read size (arbitrary value)

    IMFMediaBuffer *pBuffer = NULL;
    IMFSample *pSample = NULL;

    HRESULT hr = S_OK;
    while (SUCCEEDED(hr))
    {
        // The parser must get a newly allocated buffer each time.
        hr = MFCreateMemoryBuffer(cbReadSize, &pBuffer);
        if (FAILED(hr))
        {
            break;
        }

        // Read data into the buffer.
        hr = ReadFromByteStream(pStream, pBuffer, cbReadSize);
        if (FAILED(hr)) 
        {
            break; 
        }

        // Get the amound of data that was read.
        DWORD cbData;
        hr = pBuffer->GetCurrentLength(&cbData);
        if (FAILED(hr)) 
        { 
            break; 
        }

        if (cbData == 0)
        {
            break; // End of file.
        }

        // Send the data to the ASF splitter.
        hr = pSplitter->ParseData(pBuffer, 0, 0);
        SafeRelease(&pBuffer);
        if (FAILED(hr)) 
        { 
            break; 
        }

        // Pull samples from the splitter.
        DWORD parsingStatus = 0;
        do
        {
            WORD streamID;
            hr = pSplitter->GetNextSample(&parsingStatus, &streamID, &pSample);
            if (FAILED(hr)) 
            { 
                break; 
            }
            if (pSample == NULL)
            {
                // No samples yet. Parse more data.
                break;
            }
            if (IsRandomAccessPoint(pSample))
            {
                DisplayKeyFrame(pSample);
            }
            SafeRelease(&pSample);
            
        } while (parsingStatus & ASF_STATUSFLAGS_INCOMPLETE);
    }
    SafeRelease(&pSample);
    SafeRelease(&pBuffer);
    return hr;
}

Pemisah ASF