Создание новых пакетов данных ASF
Мультиплексер ASF — это компонент слоя WMContainer, который работает с объектом данных ASF и предоставляет приложению возможность генерировать пакеты данных ASF для потока таким образом, чтобы они соответствовали требованиям, определённым в объекте ContentInfo.
Мультиплексер имеет один вход и один выход. Он получает образец потока, содержащий данные цифрового носителя, и создает один или несколько пакетов данных, которые можно записать в контейнер ASF.
В следующем списке приводится сводка процесса создания пакетов данных ASF:
- Передайте входные данные в мультиплексер в IMFASFMultiplexer::ProcessSample.
- Собирайте пакеты данных, вызывая IMFASFMultiplexer::GetNextPacket в цикле до тех пор, пока не будут получены все полные пакеты.
- После преобразования входных данных в завершенные пакеты в мультиплексоре могут оставаться некоторые ожидающие данные, которые не были получены GetNextPacket. Вызовите IMFASFMultiplexer::Flush, чтобы упаковать ожидающие образцы и собрать их из мультиплексера, повторно вызвав GetNextPacket.
- Обновите связанные объекты заголовков ASF, вызвав метод IMFASFMultiplexer::End, чтобы отразить изменения, выполненные мультиплексером при создании пакетов данных.
На следующей схеме показано создание пакетов данных для ФАЙЛА ASF с помощью мультиплексера.
схема файла asf
Создание пакета данных ASF
После создания и инициализации мультиплексера, как описано в создании объекта мультиплексера, вызовите IMFASFMultiplexer::ProcessSample для передачи входных данных в мультиплексер, чтобы обработать их в пакеты данных. Указанные входные данные должны находиться в образце мультимедиа (интерфейс IMFSample), который может содержать один или несколько буферов мультимедиа (интерфейс IMFMediaBuffer), содержащие данные для потока. В случае транскодирования ASF в ASF образец входного носителя можно создать из разбиения, создающего пакетизованные примеры потоков. Дополнительные сведения см. в разделе «ASF Splitter».
Перед вызовом ProcessSampleубедитесь, что метка времени входного медиасэмпла является допустимым временем воспроизведения; в противном случае ProcessSample завершается ошибкой и возвращает код MF_E_NO_SAMPLE_TIMESTAMP.
Мультиплексер может принимать входные данные в виде сжатых или несжатых примеров мультимедиа с помощью ProcessSample. Мультиплексер назначает время отправки для этих образцов в зависимости от использования пропускной способности потока. Во время этого процесса мультиплексер проверяет параметры "текущего ведра" (битрейт и использование буферного окна) и может отклонять образцы, которые не соответствуют этим значениям. Пример входного носителя может не пройти проверку пропускной способности по любой из следующих причин:
- Если входной образец носителя прибыл поздно так как время отправки, назначенное последним, больше метки времени на этом образце мультимедиа. ProcessSample терпит неудачу с возвращением кода ошибки MF_E_LATE_SAMPLE.
- Если метка времени в примере входного носителя превышает назначенное время отправки (это означает переполнение буфера). Мультиплексер может игнорировать эту ситуацию, если она настроена для настройки скорости передачи, задав флаг MFASF_MULTIPLEXER_AUTOADJUST_BITRATE во время инициализации мультиплексера. Дополнительные сведения см. в разделе "Инициализация мультиплексора и настройки алгоритма Leaky Bucket" в Создание объекта мультиплексора. Если этот флаг не задан, а мультиплексер обнаруживает переполнение пропускной способности, 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, связанного с этими пакетами данных. Объект заголовка задается путем передачи объекта 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 из одного файла в другой
-
Руководство по . Написание WMA-файла с помощью кодировки CBR