Compartilhar via


Gerando novos pacotes de dados ASF

O multiplexador ASF é um componente de camada WMContainer que funciona com o Objeto de Dados ASF e fornece a um aplicativo a capacidade de gerar pacotes de dados ASF para um fluxo que corresponda aos requisitos definidos no objeto ContentInfo.

O multiplexador tem uma entrada e uma saída. Ele recebe um exemplo de fluxo que contém dados de mídia digital e produz um ou mais pacotes de dados que podem ser gravados em um contêiner ASF.

A lista a seguir resume o processo de geração de pacotes de dados ASF:

  1. Passe dados de entrada para o multiplexador em IMFASFMultiplexer::P rocessSample.
  2. Colete os pacotes de dados chamando IMFASFMultiplexer::GetNextPacket em um loop até que todos os pacotes completos sejam recuperados.
  3. Depois que os dados de entrada forem convertidos em pacotes completos, poderá haver alguns dados pendentes no multiplexador, que não foram recuperados pelo GetNextPacket. Chame IMFASFMultiplexer::Flush para empacotar os exemplos pendentes e colete-os do multiplexador chamando GetNextPacket novamente.
  4. Atualize os objetos de cabeçalho ASF associados chamando IMFASFMultiplexer::End para refletir as alterações feitas pelo multiplexador durante a geração de pacotes de dados.

O diagrama a seguir ilustra a geração de pacotes de dados para um arquivo ASF por meio do multiplexador.

diagrama mostrando a geração de pacote de dados para um arquivo asf

Criação de pacotes de dados ASF

Depois de criar e inicializar o multiplexador, conforme descrito em Criando o objeto Multiplexer, chame IMFASFMultiplexer::P rocessSample para passar dados de entrada para o multiplexador para processamento em pacotes de dados. A entrada especificada deve estar em um exemplo de mídia (interface IMFSample ) que pode ter um ou mais buffers de mídia (interface IMFMediaBuffer ) contendo os dados de um fluxo. No caso da transcodificação ASF para ASF, o exemplo de mídia de entrada pode ser gerado a partir do divisor que cria amostras de fluxo empacotados. Para obter mais informações, consulte Divisor ASF.

Antes de chamar ProcessSample, verifique se o carimbo de data/hora do exemplo de mídia de entrada é uma hora de apresentação válida; caso contrário , ProcessSample falhará e retornará o código MF_E_NO_SAMPLE_TIMESTAMP.

O multiplexador pode aceitar a entrada como amostras de mídia compactadas ou descompactadas por meio de ProcessSample. O multiplexador atribui tempos de envio a esses exemplos, dependendo do uso da largura de banda do fluxo. Durante esse processo, o multiplexador verifica os parâmetros de bucket com vazamento (taxa de bits e utilização da janela de buffer) e pode rejeitar amostras que não aderem a esses valores. O exemplo de mídia de entrada pode falhar na largura de banda marcar por um dos seguintes motivos:

  • Se o exemplo de mídia de entrada chegou atrasado porque a hora de envio atribuída pela última vez é maior que o carimbo de data/hora neste exemplo de mídia. ProcessSample falha e retorna o código de erro MF_E_LATE_SAMPLE.
  • Se o carimbo de data/hora no exemplo de mídia de entrada for anterior à hora de envio atribuída (isso indica estouro de buffer). O multiplexador poderá ignorar essa situação se estiver configurado para ajustar a taxa de bits definindo o sinalizador MFASF_MULTIPLEXER_AUTOADJUST_BITRATE durante a inicialização do multiplexador. Para obter mais informações, confira "Inicialização do Multiplexer e Configurações de bucket com vazamento" em Criando o objeto Multiplexer. Se esse sinalizador não estiver definido e o multiplexador encontrar uma sobrecarga de largura de banda, ProcessSample falhará e retornará o código de erro MF_E_BANDWIDTH_OVERRUN .

Depois que o multiplexador atribui o tempo de envio, o exemplo de mídia de entrada é adicionado à janela de envio — uma lista de exemplos de mídia de entrada ordenados por tempos de envio e prontos para serem processados em pacotes de dados. Durante a construção do pacote de dados, o exemplo de mídia de entrada é analisado e os dados relevantes são gravados em um pacote de dados como conteúdo. Um pacote de dados completo pode conter dados de um ou mais exemplos de mídia de entrada.

Quando novos exemplos de mídia de entrada chegam na janela de envio, eles são adicionados a uma fila até que haja exemplos de mídia suficientes para formar um pacote completo. Os dados em buffers de mídia contidos no exemplo de mídia de entrada não são copiados para o pacote de dados gerado. O pacote de dados contém referências aos buffers de mídia de entrada até que o exemplo de mídia de entrada tenha sido totalmente em pacote e o pacote completo tenha sido coletado do multiplexador.

Quando um pacote de dados completo está disponível, ele pode ser recuperado chamando IMFASFMultiplexer::GetNextPacket. Se você chamar ProcessSample enquanto houver pacotes completos prontos para recuperação, ele falhará e retornará o código de erro MF_E_NOTACCEPTING . Isso indica que o multiplexador não pode aceitar mais entradas e você deve chamar GetNextPacket para recuperar os pacotes em espera. Idealmente, cada chamada ProcessSample deve ser seguida por uma ou mais chamadas GetNextPacket para obter os pacotes de dados completos. Pode ser necessário mais de um exemplo de mídia de entrada para criar um pacote de dados completo. Por outro lado, os dados em um exemplo de mídia de entrada podem abranger vários pacotes. Portanto, nem todas as chamadas para ProcessSample produzirão exemplos de mídia de saída.

Se o exemplo de mídia de entrada contiver um quadro-chave indicado pelo atributo MFSampleExtension_CleanPoint , o multiplexador copiará o atributo para o pacote.

Obtendo pacotes de dados ASF

Para coletar os exemplos de mídia de saída para um pacote de dados completo gerado pelo multiplexador, chame IMFASFMultiplexer::GetNextPacket em um loop até que não haja mais amostras de mídia de saída restantes para o pacote. O seguinte lista os casos de êxito:

  • Se houver um pacote de dados completo disponível, GetNextPacket receberá o sinalizador ASF_STATUS_FLAGS_INCOMPLETE no parâmetro pdwStatusFlags ; o parâmetro ppIPacket recebe um ponteiro para o primeiro pacote de dados. Você deve chamar esse método desde que ele receba esse sinalizador. A cada iteração, ppIPacket aponta para o próximo pacote na fila.
  • Se houver apenas um pacote de dados, ppIPacket apontará para ele e o sinalizador ASF_STATUS_FLAGS_INCOMPLETE não será recebido em pdwStatusFlags.
  • GetNextPacket poderá ter êxito sem produzir pacotes de dados se o multiplexador ainda estiver em processo de empacotamento e adição de pacotes de dados. Nesse caso, ppIPacket aponta para NULL. Para continuar, você deve fornecer ao multiplexador mais amostras de mídia de entrada chamando ProcessSample.

O código de exemplo a seguir mostra uma função que gera pacotes de dados usando o multiplexador. O conteúdo do pacote de dados gerado será gravado no fluxo de bytes de dados alocado pelo chamador.

//-------------------------------------------------------------------
// 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;
}

A WriteBufferToByteStream função é mostrada no tópico IMFByteStream::Write.

Para ver um aplicativo completo que usa este exemplo de código, consulte Tutorial: Copiando fluxos ASF de um arquivo para outro.

Postar chamadas Packet-Generation

Para garantir que não haja pacotes de dados completos aguardando no multiplexador, chame IMFASFMultiplexer::Flush. Isso força o multiplexador a colocar em pacote todos os exemplos de mídia que estão em andamento. O aplicativo pode coletar esses pacotes na forma de exemplos de mídia por meio de GetNextPacket em um loop até que não haja mais pacotes a serem recuperados.

Depois que todos os exemplos de mídia forem gerados, chame IMFASFMultiplexer::End para atualizar o Objeto de Cabeçalho ASF associado a esses pacotes de dados. O Objeto Header é especificado passando o objeto ContentInfo que foi usado para inicializar o multiplexador. Essa chamada atualiza vários Objetos de Cabeçalho para refletir as alterações feitas pelo multiplexador durante a geração de pacotes de dados. Essas informações incluem contagem de pacotes, duração do envio, duração da reprodução e números de fluxo de todos os fluxos. O tamanho geral do cabeçalho também é atualizado.

Você deve garantir que End seja chamado depois que todos os pacotes de dados tiverem sido recuperados. Se houver pacotes aguardando no multiplexador, End falhará e retornará o código de erro MF_E_FLUSH_NEEDED . Nesse caso, obtenha o pacote de espera chamando Flush e GetNextPacket em um loop.

Observação

Para codificação VBR, depois de chamar End, você deve definir as estatísticas de codificação nas propriedades de codificação do objeto ContentInfo. Para obter informações sobre esse processo, confira "Como configurar o objeto ContentInfo com configurações do codificador" em Definindo propriedades no objeto ContentInfo. A lista a seguir mostra as propriedades específicas a serem definidas:

 

Multiplexador ASF

Tutorial: Copiando fluxos do ASF de um arquivo para outro

Tutorial: Escrevendo um arquivo WMA usando a codificação CBR