Partilhar via


Gerando novos pacotes de dados ASF

O multiplexador ASF é um componente da camada WMContainer que funciona com o ASF Data Object e permite a uma aplicação a capacidade de gerar pacotes de dados ASF para um fluxo que corresponde aos requisitos definidos no objeto ContentInfo.

O multiplexador tem uma entrada e uma saída. Ele recebe uma amostra 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. Passar dados de entrada para o multiplexador em IMFASFMultiplexer::ProcessSample.
  2. Colete os pacotes de dados chamando IMFASFMultiplexer::GetNextPacket em um loop até que todos os pacotes completos tenham sido recuperados.
  3. Depois que os dados de entrada foram convertidos em pacotes completos, pode haver alguns dados pendentes no multiplexador, que não foram recuperados pelo GetNextPacket. Chame IMFASFMultiplexer::Flush para empacotar as amostras pendentes e coletá-las 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 através do multiplexador.

diagrama mostrando a geração de pacotes 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 multiplexador, chame IMFASFMultiplexer::P rocessSample para passar dados de entrada para o multiplexador para processamento em pacotes de dados. A entrada especificada deve estar numa amostra de média (interface IMFSample) que pode ter um ou mais buffers de média (interface IMFMediaBuffer) contendo os dados para um stream. No caso de transcodificação ASF para ASF, a amostra de mídia de entrada pode ser originada do separador que cria amostras de fluxo empacotadas. Para obter mais informações, consulte ASF Splitter.

Antes de chamar ProcessSample, certifique-se de que o timestamp da amostra 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 entradas como amostras de mídia compactada ou não compactada através ProcessSample. O multiplexador atribui tempos de envio para essas amostras, dependendo do uso de largura de banda do fluxo. Durante esse processo, o multiplexador verifica os parâmetros do 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 verificação de largura de banda por um dos seguintes motivos:

  • Se o segmento de mídia de entrada chegou atrasado porque o último tempo de envio atribuído é maior do que o timestamp desse segmento de mídia. ProcessSample falha e retorna o código de erro MF_E_LATE_SAMPLE.
  • Se o carimbo de data/hora na amostra de mídia de entrada for anterior ao tempo de envio atribuído, isso indica uma sobrecarga de buffer. O multiplexador pode ignorar esta 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, consulte "Inicialização do Multiplexador e Configurações de Bucket com Vazamento" em Criando o Objeto Multiplexador. Se esse sinalizador não estiver definido e o multiplexador encontrar saturação 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, a amostra de mídia de entrada é adicionada à janela de envio —uma lista de amostras de mídia de entrada ordenadas por tempos de envio e prontas para serem processadas em pacotes de dados. Durante a construção do pacote de dados, a amostra de mídia de entrada é analisada e os dados relevantes são gravados em um pacote de dados como carga útil. Um pacote de dados completo pode conter dados de uma ou mais amostras de mídia de entrada.

Quando novas amostras de mídia de entrada chegam na janela de envio, elas são adicionadas a uma fila até que haja amostras de mídia suficientes para formar um pacote completo. Os dados em buffers de mídia contidos pelo exemplo de mídia de entrada não são copiados para o pacote de dados gerado. O pacote de dados mantém referências aos buffers de mídia de entrada até que a amostra de mídia de entrada tenha sido totalmente empacotada 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 entrada e você deve chamar GetNextPacket para recuperar os pacotes em espera. Idealmente, cada ProcessSample chamada deve ser seguida por uma ou mais GetNextPacket chamadas para obter os pacotes de dados completos. Pode levar mais de uma amostra de mídia de entrada para criar um pacote de dados completo. Por outro lado, os dados em uma amostra de mídia de entrada podem abranger vários pacotes. Portanto, nem todas as chamadas para ProcessSample produzirão amostras 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 recolher as amostras de saída de mídia para um pacote de dados completo gerado pelo multiplexador, chame IMFASFMultiplexer::GetNextPacket num ciclo até que não restem mais amostras de saída de mídia para o pacote. A seguir estão listados os casos de sucesso:

  • 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 aponta para ele e o sinalizador ASF_STATUS_FLAGS_INCOMPLETE não é recebido em pdwStatusFlags.
  • GetNextPacket pode ter êxito sem produzir nenhum pacote de dados se o multiplexador ainda estiver no processo de empacotamento e adição de pacotes de dados. Neste 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 função WriteBufferToByteStream é mostrada no tópico IMFByteStream::Write.

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

Publicação Packet-Generation Chamadas

Para se certificar de que não há pacotes de dados completos aguardando no multiplexador, ligue IMFASFMultiplexer::Flush. Isso força o multiplexador a empacotar todas as amostras de mídia que estão em andamento. O aplicativo pode coletar esses pacotes na forma de amostras de mídia através 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. Esta 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 algum pacote aguardando no multiplexador, End falhará e retornará o código de erro MF_E_FLUSH_NEEDED. Nesse caso, obtenha o pacote em 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, consulte "Configurando o objeto ContentInfo com configurações do codificador" em Propriedades de configuração no objeto ContentInfo. A lista a seguir mostra as propriedades específicas a serem definidas:

 

Multiplexador ASF

Tutorial: Copiando fluxos ASF de um arquivo para outro

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