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 Format Sistem Canggih (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 mencakup ukuran header dari Objek Data sebesar 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.

    Nota

    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 dari awal paket data pada 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 untuk 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 untuk mengambil offset. Pengindeks mengembalikan nilai offset yang dimulai pada batas paket. Jika Anda tidak menggunakan pengindeks, pastikan offset dimulai di awal header paket data. Jika offset yang tidak valid diteruskan ke pemisah, dan nilainya tidak menunjuk ke batas paket, ParseHeader dan GetNextSample berhasil dipanggil, tetapi GetNextSample tidak mengambil sampel apa pun dan NULL diterima dalam parameter pSample.

Jika pemecah dikonfigurasi untuk mengurai dalam arah terbalik, maka pemecah tersebut akan selalu mulai mengurai di akhir buffer media yang diteruskan ke ParseData. Oleh karena itu, untuk penguraian terbalik saat memanggil ParseData, berikan offset dalam parameter cbLength, yang menentukan panjang data, dan atur cbBufferOffset ke nol.

Membuat 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 Media Buffer.) Kemudian, teruskan media buffer ke metode IMFASFSplitter::ParseData. Anda juga dapat menentukan:

  • Posisi awal di buffer tempat pemisah harus mulai mengurai data. 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 metodeIMFMediaBuffer::GetCurrentLength.

Pemisah menghasilkan sampel media dengan merujuk data pada 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 dalam parameter pdwStatusFlags, itu berarti ada lebih banyak sampel yang perlu diambil, dan aplikasi dapat memanggil GetNextSample lagi. Jika tidak, panggil ParseData untuk meneruskan lebih banyak data ke pemisah. Untuk sampel yang dihasilkan, pemisah mengatur informasi berikut:

  • Pemisah menetapkan 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 100 unit nanodetik.
  • Jika jeda terjadi selama pembuatan sampel, pemisah mengatur atribut MFSampleExtension_Discontinuity pada sampel pertama setelah penghentian. Diskontinuitas biasanya disebabkan oleh paket yang hilang pada sambungan jaringan, data file yang rusak, atau pemisah beralih dari satu aliran sumber ke aliran sumber lain.
  • Untuk video, pembagi memeriksa apakah contoh 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 adalah variabel. 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