Exemplo n.º 1
0
Arquivo: opus.c Projeto: 0xheart0/vlc
/*****************************************************************************
 * ProcessHeaders: process Opus headers.
 *****************************************************************************/
static int ProcessHeaders( decoder_t *p_dec )
{
    ogg_packet oggpacket;

    unsigned pi_size[XIPH_MAX_HEADER_COUNT];
    void     *pp_data[XIPH_MAX_HEADER_COUNT];
    unsigned i_count;

    int i_extra = p_dec->fmt_in.i_extra;
    uint8_t *p_extra = p_dec->fmt_in.p_extra;

    /* If we have no header (e.g. from RTP), make one. */
    bool b_dummy_header = false;
    if( !i_extra )
    {
        OpusHeader header;
        opus_prepare_header( p_dec->fmt_in.audio.i_channels,
                             p_dec->fmt_in.audio.i_rate, &header );
        if( opus_write_header( &p_extra, &i_extra, &header,
                               opus_get_version_string() ) )
            return VLC_ENOMEM;
        b_dummy_header = true;
    }

    if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
                           i_extra, p_extra ) )
    {
        if( b_dummy_header )
            free( p_extra );
        return VLC_EGENERIC;
    }

    if( i_count < 2 )
    {
        if( b_dummy_header )
            free( p_extra );
        return VLC_EGENERIC;
    }

    oggpacket.granulepos = -1;
    oggpacket.e_o_s = 0;
    oggpacket.packetno = 0;

    /* Take care of the initial Opus header */
    oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
    oggpacket.bytes  = pi_size[0];
    oggpacket.packet = pp_data[0];
    int ret = ProcessInitialHeader( p_dec, &oggpacket );

    if (ret != VLC_SUCCESS)
        msg_Err( p_dec, "initial Opus header is corrupted" );

    if( b_dummy_header )
        free( p_extra );

    return ret;
}
Exemplo n.º 2
0
Arquivo: opus.c Projeto: MSalmo/vlc
static int OpenEncoder(vlc_object_t *p_this)
{
    encoder_t *enc = (encoder_t *)p_this;

    if (enc->fmt_out.i_codec != VLC_CODEC_OPUS)
        return VLC_EGENERIC;

    encoder_sys_t *sys = malloc(sizeof(*sys));
    if (!sys)
        return VLC_ENOMEM;

    int status = VLC_SUCCESS;
    sys->buffer = NULL;
    sys->enc = NULL;

    enc->pf_encode_audio = Encode;
    enc->fmt_in.i_codec = VLC_CODEC_FL32;
    enc->fmt_in.audio.i_rate = /* Only 48kHz */
    enc->fmt_out.audio.i_rate = 48000;
    enc->fmt_out.audio.i_channels = enc->fmt_in.audio.i_channels;

    OpusHeader header;

    if (opus_prepare_header(enc->fmt_out.audio.i_channels,
            enc->fmt_out.audio.i_rate,
            &header))
    {
        msg_Err(enc, "Failed to prepare header.");
        status = VLC_ENOMEM;
        goto error;
    }

    /* needed for max encoded size calculation */
    sys->nb_streams = header.nb_streams;

    int err;
    sys->enc =
        opus_multistream_surround_encoder_create(enc->fmt_in.audio.i_rate,
                enc->fmt_in.audio.i_channels, header.channel_mapping,
                &header.nb_streams, &header.nb_coupled, header.stream_map,
                OPUS_APPLICATION_AUDIO, &err);

    if (err != OPUS_OK)
    {
        msg_Err(enc, "Could not create encoder: error %d", err);
        sys->enc = NULL;
        status = VLC_EGENERIC;
        goto error;
    }

    /* TODO: vbr, bitrate, fec */

    /* Buffer for incoming audio, since opus only accepts frame sizes that are
       multiples of 2.5ms */
    enc->p_sys = sys;
    sys->buffer = malloc(OPUS_FRAME_SIZE * header.channels * sizeof(float));
    if (!sys->buffer) {
        status = VLC_ENOMEM;
        goto error;
    }

    sys->i_nb_samples = 0;

    sys->i_samples_delay = 0;
    int ret = opus_multistream_encoder_ctl(enc->p_sys->enc,
            OPUS_GET_LOOKAHEAD(&sys->i_samples_delay));
    if (ret != OPUS_OK)
        msg_Err(enc, "Unable to get number of lookahead samples: %s\n",
                opus_strerror(ret));

    header.preskip = sys->i_samples_delay;

    /* Now that we have preskip, we can write the header to extradata */
    if (opus_write_header((uint8_t **) &enc->fmt_out.p_extra,
                          &enc->fmt_out.i_extra, &header))
    {
        msg_Err(enc, "Failed to write header.");
        status = VLC_ENOMEM;
        goto error;
    }

    if (sys->i_samples_delay > 0)
    {
        const unsigned padding_samples = sys->i_samples_delay *
            enc->fmt_out.audio.i_channels;
        sys->padding = block_Alloc(padding_samples * sizeof(float));
        if (!sys->padding) {
            status = VLC_ENOMEM;
            goto error;
        }
        sys->padding->i_nb_samples = sys->i_samples_delay;
        float *pad_ptr = (float *) sys->padding->p_buffer;
        memset(pad_ptr, 0, padding_samples * sizeof(float));
    }
    else
    {
        sys->padding = NULL;
    }

    return status;

error:
    if (sys->enc)
        opus_multistream_encoder_destroy(sys->enc);
    free(sys->buffer);
    free(sys);
    return status;
}