Поделиться через


Создание новых пакетов данных ASF

Мультиплексор ASF — это компонент слоя WMContainer, который работает с объектом данных ASF и предоставляет приложению возможность создавать пакеты данных ASF для потока, соответствующего требованиям, определенным в объекте ContentInfo.

Мультиплексер имеет один вход и один выход. Он получает пример потока, содержащий данные цифрового носителя, и создает один или несколько пакетов данных, которые могут быть записаны в контейнер ASF.

В следующем списке приводится сводка процесса создания пакетов данных ASF:

  1. Передайте входные данные в мультиплексер в IMFASFMultiplexer::P rocessSample.
  2. Сбор пакетов данных путем вызова IMFASFMultiplexer::GetNextPacket в цикле до получения всех полных пакетов.
  3. После преобразования входных данных в полные пакеты могут быть некоторые ожидающие данные в мультиплексе, которые не были получены GetNextPacket. Вызовите IMFASFMultiplexer::Flush, чтобы упаковать ожидающие образцы и собрать их из мультиплексора, вызвав GetNextPacket еще раз.
  4. Обновите связанные объекты заголовков ASF, вызвав IMFASFMultiplexer::End , чтобы отразить изменения, внесенные мультиплексером во время создания пакетов данных.

На следующей схеме показано создание пакетов данных для ФАЙЛА ASF с помощью мультиплексера.

diagram showing data packet generation for an asf file

Создание пакета данных ASF

После создания и инициализации мультиплексера, как описано в разделе "Создание объекта multiplexer", вызовите IMFASFMultiplexer::P rocessSample для передачи входных данных в мультиплексор для обработки пакетов данных. Указанные входные данные должны находиться в образце мультимедиа (интерфейс IMFSample ), который может содержать один или несколько буферов мультимедиа (интерфейс IMFMediaBuffer ), содержащий данные для потока. В случае перекодирования ASF в ASF образец входного носителя можно создать из разбиения, создающего пакетные образцы потоков. Дополнительные сведения см. в разделе "Разделение ASF".

Перед вызовом ProcessSample убедитесь, что метка времени входного носителя является допустимым временем презентации; в противном случае ProcessSample завершается ошибкой и возвращает код MF_E_NO_SAMPLE_TIMESTAMP.

Мультиплексер может принимать входные данные как сжатые или несжатые образцы мультимедиа с помощью ProcessSample. Мультиплексор назначает время отправки этим примерам в зависимости от использования пропускной способности потока. Во время этого процесса мультиплексор проверяет параметры утечки контейнера (скорость битов и использование буферного окна) и может отклонять примеры, которые не соответствуют этим значениям. В примере входного носителя может завершиться сбой проверки пропускной способности по следующим причинам:

  • Если входной образец мультимедиа прибыл поздно, так как время отправки, назначенное последней, больше отметки времени в этом образце мультимедиа. ProcessSample завершается сбоем и возвращает код ошибки MF_E_LATE_SAMPLE .
  • Если метка времени входного носителя превышает назначенное время отправки (это означает переполнение буфера). Мультиплексор может игнорировать эту ситуацию, если она настроена для настройки скорости передачи, задав флаг MFASF_MULTIPLEXER_AUTOADJUST_BITRATE во время инициализации мультиплексора. Дополнительные сведения см. в разделе "Инициализация мультиплексора и утечка контейнеров Параметры" в разделе "Создание объекта Multiplexer". Если этот флаг не задан, и мультиплексер обнаруживает переполнение пропускной способности, ProcessSample завершается сбоем и возвращает код ошибки MF_E_BANDWIDTH_OVERRUN .

После того как мультиплексер назначает время отправки, входной образец мультимедиа добавляется в окно отправки — список образцов входных носителей, упорядоченных по времени отправки и готовых к обработке в пакеты данных. Во время создания пакета данных образец входного носителя анализируется, и соответствующие данные записываются в пакет данных в виде полезных данных. Полный пакет данных может содержать данные из одного или нескольких примеров входных носителей.

Когда новые входные примеры мультимедиа поступают в окно отправки, они добавляются в очередь, пока не будет достаточно примеров мультимедиа для формирования одного полного пакета. Данные в буферах мультимедиа, содержащихся в примере входного носителя, не копируются в созданный пакет данных. Пакет данных содержит ссылки на входные буферы мультимедиа, пока входной образец носителя не будет полностью пакетизирован и полный пакет будет собран из мультиплексера.

Когда доступен полный пакет данных, его можно получить, вызвав IMFASFMultiplexer::GetNextPacket. Если вы вызываете ProcessSample , пока есть полные пакеты, готовые к извлечению, происходит сбой и возвращается код ошибки MF_E_NOTACCEPTING . Это означает, что мультиплексер не может принимать дополнительные входные данные, и для получения ожидающих пакетов необходимо вызвать GetNextPacket . В идеале за каждым вызовом ProcessSample следует один или несколько вызовов GetNextPacket , чтобы получить полные пакеты данных. Чтобы создать полный пакет данных, может потребоваться несколько входных носителей. И наоборот, данные в одном примере входного носителя могут охватывать несколько пакетов. Поэтому не все вызовы ProcessSample будут выдавать выходные примеры мультимедиа.

Если входной образец носителя содержит ключевой кадр, указанный атрибутом MFSampleExtension_CleanPoint , мультиплексер копирует атрибут в пакет.

Получение пакетов данных ASF

Чтобы собрать примеры выходных носителей для полного пакета данных, созданного мультиплексером, вызовите IMFASFMultiplexer::GetNextPacket в цикле, пока не останется больше выходных образцов носителей, оставшихся для пакета. Ниже перечислены случаи успешного выполнения.

  • Если доступен полный пакет данных, GetNextPacket получает флаг ASF_STATUS_FLAGS_INCOMPLETE в параметре pdwStatusFlags ; Параметр ppIPacket получает указатель на первый пакет данных. Этот метод необходимо вызвать до тех пор, пока он получает этот флаг. При каждой итерации ppIPacket указывает на следующий пакет в очереди.
  • Если существует только один пакет данных, ppIPacket указывает на него и флаг ASF_STATUS_FLAGS_INCOMPLETE не получается в pdwStatusFlags.
  • GetNextPacket может быть успешным без получения пакетов данных, если мультиплексер по-прежнему находится в процессе пакетизации и добавления пакетов данных. В этом случае ppIPacket указывает на NULL. Чтобы продолжить, необходимо предоставить мультиплексор с дополнительными входными примерами мультимедиа, вызвав ProcessSample.

В следующем примере кода показана функция, которая создает пакеты данных с помощью мультиплексера. Созданное содержимое пакета данных будет записано в поток байтов данных, выделенный вызывающим объектом.

//-------------------------------------------------------------------
// GenerateASFDataPackets
// 
// Gets data packets from the mux. This function is called after 
// calling IMFASFMultiplexer::ProcessSample. 
//-------------------------------------------------------------------

HRESULT GenerateASFDataPackets( 
    IMFASFMultiplexer *pMux, 
    IMFByteStream *pDataStream
    )
{
    HRESULT hr = S_OK;

    IMFSample *pOutputSample = NULL;
    IMFMediaBuffer *pDataPacketBuffer = NULL;

    DWORD dwMuxStatus = ASF_STATUSFLAGS_INCOMPLETE;

    while (dwMuxStatus & ASF_STATUSFLAGS_INCOMPLETE)
    {
        hr = pMux->GetNextPacket(&dwMuxStatus, &pOutputSample);

        if (FAILED(hr))
        {
            break;
        }

        if (pOutputSample)
        {
            //Convert to contiguous buffer
            hr = pOutputSample->ConvertToContiguousBuffer(&pDataPacketBuffer);
            
            if (FAILED(hr))
            {
                break;
            }

            //Write buffer to byte stream
            hr = WriteBufferToByteStream(pDataStream, pDataPacketBuffer, NULL);

            if (FAILED(hr))
            {
                break;
            }
        }

        SafeRelease(&pDataPacketBuffer);
        SafeRelease(&pOutputSample);
    }

    SafeRelease(&pOutputSample);
    SafeRelease(&pDataPacketBuffer);
    return hr;
}

Функция WriteBufferToByteStream показана в разделе IMFByteStream::Write.

Полный пример приложения, использующего этот пример кода, см. в руководстве по копированию ASF Потоки из одного файла в другой.

После Packet-Generation звонков

Чтобы убедиться, что в мультиплексе нет полных пакетов данных, вызовите IMFASFMultiplexer::Flush. Это заставляет мультиплексер пакетизировать все выполняемые образцы мультимедиа. Приложение может собирать эти пакеты в виде примеров мультимедиа с помощью GetNextPacket в цикле, пока не осталось больше пакетов для извлечения.

После создания всех образцов мультимедиа вызовите IMFASFMultiplexer::End для обновления объекта заголовка ASF, связанного с этими пакетами данных. Объект header задается путем передачи объекта ContentInfo, который использовался для инициализации мультиплексера. Этот вызов обновляет различные объекты заголовков, чтобы отразить изменения, внесенные мультиплексером во время создания пакетов данных. Эти сведения включают количество пакетов, длительность отправки, длительность воспроизведения и номера потоков всех потоков. Общий размер заголовка также обновляется.

Необходимо убедиться, что end вызывается после получения всех пакетов данных. Если в мультиплексе есть какие-либо пакеты, end завершится ошибкой и вернет код ошибки MF_E_FLUSH_NEEDED . В этом случае получите пакет ожидания, вызвав Flush и GetNextPacket в цикле.

Примечание

Для кодировки VBR после вызова End необходимо задать статистику кодирования в свойствах кодирования объекта ContentInfo. Сведения об этом процессе см. в разделе "Настройка объекта ContentInfo с помощью кодировщика Параметры" статьи "Настройка свойств в объекте ContentInfo". В следующем списке показаны определенные свойства, которые необходимо задать:

  • MFPKEY_RAVG — это средняя скорость передачи содержимого VBR.
  • MFPKEY_BAVG — это окно буфера для средней скорости бита.
  • MFPKEY_RMAX — это пиковая скорость передачи содержимого VBR.
  • MFPKEY_BMAX — это окно буфера пиковой нагрузки.

 

Мультиплексор ASF

Руководство по копированию Потоки ASF из одного файла в другой

Руководство по написанию WMA-файла с помощью кодировки CBR