Exemple #1
0
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
    audio_output_t * p_aout = (audio_output_t *)inUserData;
    aout_buffer_t *   p_buffer = NULL;

    if (p_aout) {
        struct aout_sys_t * p_sys = p_aout->sys;
        aout_packet_t * packet = &p_sys->packet;

        if (packet)
        {
            vlc_mutex_lock( &packet->lock );
            p_buffer = aout_FifoPop2( &packet->fifo );
            vlc_mutex_unlock( &packet->lock );
        }
    }

    if ( p_buffer != NULL ) {
        vlc_memcpy( inBuffer->mAudioData, p_buffer->p_buffer, p_buffer->i_buffer );
        inBuffer->mAudioDataByteSize = p_buffer->i_buffer;
        aout_BufferFree( p_buffer );
    } else {
        vlc_memset( inBuffer->mAudioData, 0, inBuffer->mAudioDataBytesCapacity );
        inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
    }
    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}
Exemple #2
0
/*****************************************************************************
 * Thread: thread used to DMA the data to the device
 *****************************************************************************/
static void* Thread( vlc_object_t *p_this )
{
    aout_instance_t * p_aout = (aout_instance_t*)p_this;
    aout_buffer_t * p_buffer;
    struct aout_sys_t * p_sys = p_aout->output.p_sys;
    PCMAudioPlayer * pPlayer = p_sys->pPlayer;
    int canc = vlc_savecancel ();

    while( vlc_object_alive (p_aout) )
    {
        pPlayer->WaitForBuffer();

        vlc_mutex_lock( &p_aout->output_fifo_lock );
        p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
        vlc_mutex_unlock( &p_aout->output_fifo_lock );

#define i p_sys->nNextBufferIndex
        if( p_buffer == NULL )
        {
            vlc_memset( p_aout, p_sys->ppBuffers[ i ], 0,
                                      p_sys->nBufferSize );
        }
        else
        {
            InterleaveS16( (int16_t *)p_buffer->p_buffer,
                           (int16_t *)p_sys->ppBuffers[ i ] );
            aout_BufferFree( p_buffer );
        }

        if( !pPlayer->QueueBuffer( (s16 *)p_sys->ppBuffers[ i ],
                                   p_sys->nBufferSize / 2 ) )
        {
            msg_Err( p_aout, "QueueBuffer failed" );
        }

        i = (i + 1) % p_sys->nBuffers;
#undef i
    }

    vlc_restorecancel (canc);
    return NULL;
}
Exemple #3
0
/* This routine will be called by the PortAudio engine when audio is needed.
 * It may called at interrupt level on some machines so don't do anything
 * that could mess up the system like calling malloc() or free().
 */
static int paCallback( const void *inputBuffer, void *outputBuffer,
                       unsigned long framesPerBuffer,
                       const PaStreamCallbackTimeInfo *paDate,
                       PaStreamCallbackFlags statusFlags, void *p_cookie )
{
    VLC_UNUSED( inputBuffer ); VLC_UNUSED( statusFlags );

    struct aout_sys_t *p_sys = (struct aout_sys_t*) p_cookie;
    aout_instance_t   *p_aout = p_sys->p_aout;
    aout_buffer_t     *p_buffer;
    mtime_t out_date;

    out_date = mdate() + (mtime_t) ( 1000000 *
        ( paDate->outputBufferDacTime - paDate->currentTime ) );
    p_buffer = aout_OutputNextBuffer( p_aout, out_date, true );

    if ( p_buffer != NULL )
    {
        if( p_sys->b_chan_reorder )
        {
            /* Do the channel reordering here */
            aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes,
                                 p_sys->i_channels, p_sys->pi_chan_table,
                                 p_sys->i_bits_per_sample );
        }
        vlc_memcpy( outputBuffer, p_buffer->p_buffer,
                    framesPerBuffer * p_sys->i_sample_size );
        /* aout_BufferFree may be dangereous here, but then so is
         * aout_OutputNextBuffer (calls aout_BufferFree internally).
         * one solution would be to link the no longer useful buffers
         * in a second fifo (in aout_OutputNextBuffer too) and to
         * wait until we are in Play to do the actual free.
         */
        aout_BufferFree( p_buffer );
    }
    else
        /* Audio output buffer shortage -> stop the fill process and wait */
    {
        vlc_memset( outputBuffer, 0, framesPerBuffer * p_sys->i_sample_size );
    }
    return 0;
}
Exemple #4
0
/*****************************************************************************
 * DoWork: convert a buffer
 *****************************************************************************/
static block_t *DoWork( filter_t * p_filter, block_t *p_in_buf )
{
    /* AC3 is natively big endian. Most SPDIF devices have the native
     * endianness of the computer system.
     * On Mac OS X however, little endian devices are also common.
     */
    static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
    static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
    uint16_t i_frame_size = p_in_buf->i_buffer / 2;
    uint8_t * p_in = p_in_buf->p_buffer;

    block_t *p_out_buf = filter_NewAudioBuffer( p_filter, AOUT_SPDIF_SIZE );
    if( !p_out_buf )
        goto out;
    uint8_t * p_out = p_out_buf->p_buffer;

    /* Copy the S/PDIF headers. */
    if( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
    {
        vlc_memcpy( p_out, p_sync_be, 6 );
        p_out[4] = p_in[5] & 0x7; /* bsmod */
        SetWBE( p_out + 6, i_frame_size << 4 );
        vlc_memcpy( &p_out[8], p_in, i_frame_size * 2 );
    }
    else
    {
        vlc_memcpy( p_out, p_sync_le, 6 );
        p_out[5] = p_in[5] & 0x7; /* bsmod */
        SetWLE( p_out + 6, i_frame_size << 4 );
        swab( p_in, &p_out[8], i_frame_size * 2 );
    }
    vlc_memset( p_out + 8 + i_frame_size * 2, 0,
                AOUT_SPDIF_SIZE - i_frame_size * 2 - 8 );

    p_out_buf->i_dts = p_in_buf->i_dts;
    p_out_buf->i_pts = p_in_buf->i_pts;
    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = AOUT_SPDIF_SIZE;
out:
    block_Release( p_in_buf );
    return p_out_buf;
}
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
    aout_instance_t * p_aout = (aout_instance_t *)inUserData;
    aout_buffer_t *   p_buffer = NULL;

    if (p_aout) {
        vlc_mutex_lock( &p_aout->output_fifo_lock );
        p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
        vlc_mutex_unlock( &p_aout->output_fifo_lock );
    }

    if ( p_buffer != NULL ) {
        vlc_memcpy( inBuffer->mAudioData, p_buffer->p_buffer, p_buffer->i_buffer );
        inBuffer->mAudioDataByteSize = p_buffer->i_buffer;
        aout_BufferFree( p_buffer );
    } else {
        vlc_memset( inBuffer->mAudioData, 0, inBuffer->mAudioDataBytesCapacity );
        inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
    }
    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}
Exemple #6
0
/*****************************************************************************
 * SDLCallback: what to do once SDL has played sound samples
 *****************************************************************************/
static void SDLCallback( void * _p_aout, uint8_t * p_stream, int i_len )
{
    aout_instance_t * p_aout = (aout_instance_t *)_p_aout;
    aout_buffer_t *   p_buffer;

    /* SDL is unable to call us at regular times, or tell us its current
     * hardware latency, or the buffer state. So we just pop data and throw
     * it at SDL's face. Nah. */

    vlc_mutex_lock( &p_aout->output_fifo_lock );
    p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
    vlc_mutex_unlock( &p_aout->output_fifo_lock );

    if ( p_buffer != NULL )
    {
        vlc_memcpy( p_stream, p_buffer->p_buffer, i_len );
        aout_BufferFree( p_buffer );
    }
    else
    {
        vlc_memset( p_stream, 0, i_len );
    }
}
Exemple #7
0
/* This routine will be called by the PortAudio engine when audio is needed.
 * It may called at interrupt level on some machines so don't do anything
 * that could mess up the system like calling malloc() or free().
 */
static int paCallback( const void *inputBuffer, void *outputBuffer,
                       unsigned long framesPerBuffer,
                       const PaStreamCallbackTimeInfo *paDate,
                       PaStreamCallbackFlags statusFlags, void *p_cookie )
{
    VLC_UNUSED( inputBuffer ); VLC_UNUSED( statusFlags );

    struct aout_sys_t *p_sys = (struct aout_sys_t*) p_cookie;
    audio_output_t   *p_aout = p_sys->p_aout;
    aout_buffer_t     *p_buffer;
    mtime_t out_date;

    out_date = mdate() + (mtime_t) ( 1000000 *
        ( paDate->outputBufferDacTime - paDate->currentTime ) );
    p_buffer = aout_PacketNext( p_aout, out_date );

    if ( p_buffer != NULL )
    {
        if( p_sys->b_chan_reorder )
        {
            /* Do the channel reordering here */
            aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
                                 p_sys->i_channels, p_sys->pi_chan_table,
                                 p_sys->i_bits_per_sample );
        }
        vlc_memcpy( outputBuffer, p_buffer->p_buffer,
                    framesPerBuffer * p_sys->i_sample_size );
        aout_BufferFree( p_buffer );
    }
    else
        /* Audio output buffer shortage -> stop the fill process and wait */
    {
        vlc_memset( outputBuffer, 0, framesPerBuffer * p_sys->i_sample_size );
    }
    return 0;
}
/*****************************************************************************
 * Render: displays previously rendered output
 *****************************************************************************
 * This function send the currently rendered image to Distort image, waits
 * until it is displayed and switch the two rendering buffers, preparing next
 * frame.
 *****************************************************************************/
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
    picture_t *p_outpic;
    int i_index;
    double f_angle;
    mtime_t new_date = mdate();

    if( !p_pic ) return NULL;

    p_outpic = filter_NewPicture( p_filter );
    if( !p_outpic )
    {
        picture_Release( p_pic );
        return NULL;
    }

    p_filter->p_sys->f_angle += (new_date - p_filter->p_sys->last_date) / 200000.0;
    p_filter->p_sys->last_date = new_date;
    f_angle = p_filter->p_sys->f_angle;

    for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
    {
        int i_line, i_num_lines, i_visible_pitch, i_pixel_pitch, i_offset,
            i_visible_pixels;
        uint8_t black_pixel;
        uint8_t *p_in, *p_out;

        p_in = p_pic->p[i_index].p_pixels;
        p_out = p_outpic->p[i_index].p_pixels;

        i_num_lines = p_pic->p[i_index].i_visible_lines;
        i_visible_pitch = p_pic->p[i_index].i_visible_pitch;
        i_pixel_pitch = p_pic->p[i_index].i_pixel_pitch;
        switch( p_filter->fmt_in.video.i_chroma )
        {
            CASE_PACKED_YUV_422
                // Quick hack to fix u/v inversion occuring with 2 byte pixel pitch
                i_pixel_pitch *= 2;
                break;
        }
        i_visible_pixels = i_visible_pitch/i_pixel_pitch;

        black_pixel = ( p_pic->i_planes > 1 && i_index == Y_PLANE ) ? 0x00
                                                                    : 0x80;

        /* Ok, we do 3 times the sin() calculation for each line. So what ? */
        for( i_line = 0 ; i_line < i_num_lines ; i_line++ )
        {
            /* Calculate today's offset, don't go above 1/20th of the screen */
            i_offset = (int)( (double)(i_visible_pixels)
                         * sin( f_angle + 10.0 * (double)i_line
                                               / (double)i_num_lines )
                         / 20.0 )*i_pixel_pitch;

            if( i_offset )
            {
                if( i_offset < 0 )
                {
                    vlc_memcpy( p_out, p_in - i_offset,
                                i_visible_pitch + i_offset );
                    p_in += p_pic->p[i_index].i_pitch;
                    p_out += p_outpic->p[i_index].i_pitch;
                    vlc_memset( p_out + i_offset, black_pixel, -i_offset );
                }
                else
                {
                    vlc_memcpy( p_out + i_offset, p_in,
                                i_visible_pitch - i_offset );
                    vlc_memset( p_out, black_pixel, i_offset );
                    p_in += p_pic->p[i_index].i_pitch;
                    p_out += p_outpic->p[i_index].i_pitch;
                }
            }
            else
            {
                vlc_memcpy( p_out, p_in, i_visible_pitch );
                p_in += p_pic->p[i_index].i_pitch;
                p_out += p_outpic->p[i_index].i_pitch;
            }

        }
    }

    return CopyInfoAndRelease( p_outpic, p_pic );
}
Exemple #9
0
/*****************************************************************************
 * Render: displays previously rendered output
 *****************************************************************************
 * This function send the currently rendered image to Distort image, waits
 * until it is displayed and switch the two rendering buffers, preparing next
 * frame.
 *****************************************************************************/
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
    picture_t *p_outpic;

    unsigned int w, h;
    int x,y;
    uint8_t u,v;

    picture_t *p_converted;
    video_format_t fmt_out;
    memset( &fmt_out, 0, sizeof(video_format_t) );
    fmt_out.p_palette = NULL;

    if( !p_pic ) return NULL;

    p_outpic = filter_NewPicture( p_filter );
    if( !p_outpic )
    {
        picture_Release( p_pic );
        return NULL;
    }

    if( !p_filter->p_sys->p_image )
        p_filter->p_sys->p_image = image_HandlerCreate( p_filter );

    /* chrominance */
    u = p_filter->p_sys->u;
    v = p_filter->p_sys->v;
    for( y = 0; y<p_outpic->p[U_PLANE].i_lines; y++)
    {
        vlc_memset(
                p_outpic->p[U_PLANE].p_pixels+y*p_outpic->p[U_PLANE].i_pitch,
                u, p_outpic->p[U_PLANE].i_pitch );
        vlc_memset(
                p_outpic->p[V_PLANE].p_pixels+y*p_outpic->p[V_PLANE].i_pitch,
                v, p_outpic->p[V_PLANE].i_pitch );
        if( v == 0 && u != 0 )
            u --;
        else if( u == 0xff )
            v --;
        else if( v == 0xff )
            u ++;
        else if( u == 0 )
            v ++;
    }

    /* luminance */
    vlc_memcpy( p_outpic->p[Y_PLANE].p_pixels, p_pic->p[Y_PLANE].p_pixels,
                p_outpic->p[Y_PLANE].i_lines * p_outpic->p[Y_PLANE].i_pitch );

    /* image visualization */
    fmt_out = p_filter->fmt_out.video;
    fmt_out.i_width = p_filter->fmt_out.video.i_width*p_filter->p_sys->scale/150;
    fmt_out.i_height = p_filter->fmt_out.video.i_height*p_filter->p_sys->scale/150;
    p_converted = image_Convert( p_filter->p_sys->p_image, p_pic,
                                 &(p_pic->format), &fmt_out );

    if( p_converted )
    {
#define copyimage( plane, b ) \
        for( y=0; y<p_converted->p[plane].i_visible_lines; y++) { \
        for( x=0; x<p_converted->p[plane].i_visible_pitch; x++) { \
            int nx, ny; \
            if( p_filter->p_sys->yinc == 1 ) \
                ny= y; \
            else \
                ny = p_converted->p[plane].i_visible_lines-y; \
            if( p_filter->p_sys->xinc == 1 ) \
                nx = x; \
            else \
                nx = p_converted->p[plane].i_visible_pitch-x; \
            p_outpic->p[plane].p_pixels[(p_filter->p_sys->x*b+nx)+(ny+p_filter->p_sys->y*b)*p_outpic->p[plane].i_pitch ] = p_converted->p[plane].p_pixels[y*p_converted->p[plane].i_pitch+x]; \
        } }
        copyimage( Y_PLANE, 2 );
        copyimage( U_PLANE, 1 );
        copyimage( V_PLANE, 1 );
#undef copyimage

        picture_Release( p_converted );
    }
    else
    {
        msg_Err( p_filter, "Image scaling failed miserably." );
    }

    p_filter->p_sys->x += p_filter->p_sys->xinc;
    p_filter->p_sys->y += p_filter->p_sys->yinc;

    p_filter->p_sys->scale += p_filter->p_sys->scaleinc;
    if( p_filter->p_sys->scale >= 50 ) p_filter->p_sys->scaleinc = -1;
    if( p_filter->p_sys->scale <= 1 ) p_filter->p_sys->scaleinc = 1;

    w = p_filter->fmt_out.video.i_width*p_filter->p_sys->scale/150;
    h = p_filter->fmt_out.video.i_height*p_filter->p_sys->scale/150;
    if( p_filter->p_sys->x*2 + w >= p_filter->fmt_out.video.i_width )
        p_filter->p_sys->xinc = -1;
    if( p_filter->p_sys->x <= 0 )
        p_filter->p_sys->xinc = 1;

    if( p_filter->p_sys->x*2 + w >= p_filter->fmt_out.video.i_width )
        p_filter->p_sys->x = (p_filter->fmt_out.video.i_width-w)/2;
    if( p_filter->p_sys->y*2 + h >= p_filter->fmt_out.video.i_height )
        p_filter->p_sys->y = (p_filter->fmt_out.video.i_height-h)/2;

    if( p_filter->p_sys->y*2 + h >= p_filter->fmt_out.video.i_height )
        p_filter->p_sys->yinc = -1;
    if( p_filter->p_sys->y <= 0 )
        p_filter->p_sys->yinc = 1;

    for( y = 0; y< 16; y++ )
    {
        if( p_filter->p_sys->v == 0 && p_filter->p_sys->u != 0 )
            p_filter->p_sys->u -= 1;
        else if( p_filter->p_sys->u == 0xff )
            p_filter->p_sys->v -= 1;
        else if( p_filter->p_sys->v == 0xff )
            p_filter->p_sys->u += 1;
        else if( p_filter->p_sys->u == 0 )
            p_filter->p_sys->v += 1;
    }

    return CopyInfoAndRelease( p_outpic, p_pic );
}
Exemple #10
0
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    int i,j;
    int i_lines = p_pic->p[ A_PLANE ].i_lines;
    int i_pitch = p_pic->p[ A_PLANE ].i_pitch;
    uint8_t *p_a = p_pic->p[ A_PLANE ].p_pixels;
    uint8_t *p_at;
    uint8_t *p_u = p_pic->p[ U_PLANE ].p_pixels;
    uint8_t *p_v = p_pic->p[ V_PLANE ].p_pixels;
    uint8_t umin, umax, vmin, vmax;

    if( p_pic->format.i_chroma != VLC_CODEC_YUVA )
    {
        msg_Err( p_filter,
                 "Unsupported input chroma \"%4.4s\". "
                 "Bluescreen can only use \"YUVA\".",
                 (char*)&p_pic->format.i_chroma );
        return NULL;
    }

    p_sys->p_at = xrealloc( p_sys->p_at,
                            i_lines * i_pitch * sizeof( uint8_t ) );
    p_at = p_sys->p_at;

    vlc_mutex_lock( &p_sys->lock );
    umin = p_sys->i_u - p_sys->i_ut >= 0x00 ? p_sys->i_u - p_sys->i_ut : 0x00;
    umax = p_sys->i_u + p_sys->i_ut <= 0xff ? p_sys->i_u + p_sys->i_ut : 0xff;
    vmin = p_sys->i_v - p_sys->i_vt >= 0x00 ? p_sys->i_v - p_sys->i_vt : 0x00;
    vmax = p_sys->i_v + p_sys->i_vt <= 0xff ? p_sys->i_v + p_sys->i_vt : 0xff;
    vlc_mutex_unlock( &p_sys->lock );

    for( i = 0; i < i_lines*i_pitch; i++ )
    {
        if(    p_u[i] < umax && p_u[i] > umin
            && p_v[i] < vmax && p_v[i] > vmin )
        {
            p_at[i] = 0x00;
        }
        else
        {
            p_at[i] = 0xff;
        }
    }
    /* Gaussian convolution to make it look cleaner */
    vlc_memset( p_a, 0, 2 * i_pitch );
    for( i = 2; i < i_lines - 2; i++ )
    {
        p_a[i*i_pitch] = 0x00;
        p_a[i*i_pitch+1] = 0x00;
        for( j = 2; j < i_pitch - 2; j ++ )
        {
            p_a[i*i_pitch+j] = (uint8_t)((
              /* 2 rows up */
                ( p_at[(i-2)*i_pitch+j-2]<<1 )
              + ( p_at[(i-2)*i_pitch+j-1]<<2 )
              + ( p_at[(i-2)*i_pitch+j]<<2 )
              + ( p_at[(i-2)*i_pitch+j+1]<<2 )
              + ( p_at[(i-2)*i_pitch+j+2]<<1 )
              /* 1 row up */
              + ( p_at[(i-1)*i_pitch+j-2]<<2 )
              + ( p_at[(i-1)*i_pitch+j-1]<<3 )
              + ( p_at[(i-1)*i_pitch+j]*12 )
              + ( p_at[(i-1)*i_pitch+j+1]<<3 )
              + ( p_at[(i-1)*i_pitch+j+2]<<2 )
              /* */
              + ( p_at[i*i_pitch+j-2]<<2 )
              + ( p_at[i*i_pitch+j-1]*12 )
              + ( p_at[i*i_pitch+j]<<4 )
              + ( p_at[i*i_pitch+j+1]*12 )
              + ( p_at[i*i_pitch+j+2]<<2 )
              /* 1 row down */
              + ( p_at[(i+1)*i_pitch+j-2]<<2 )
              + ( p_at[(i+1)*i_pitch+j-1]<<3 )
              + ( p_at[(i+1)*i_pitch+j]*12 )
              + ( p_at[(i+1)*i_pitch+j+1]<<3 )
              + ( p_at[(i+1)*i_pitch+j+2]<<2 )
              /* 2 rows down */
              + ( p_at[(i+2)*i_pitch+j-2]<<1 )
              + ( p_at[(i+2)*i_pitch+j-1]<<2 )
              + ( p_at[(i+2)*i_pitch+j]<<2 )
              + ( p_at[(i+2)*i_pitch+j+1]<<2 )
              + ( p_at[(i+2)*i_pitch+j+2]<<1 )
              )/152);
              if( p_a[i*i_pitch+j] < 0xbf ) p_a[i*i_pitch+j] = 0x00;
        }
    }
    return p_pic;
}
Exemple #11
0
/**
 * Rearranges audio blocks in correct number of samples.
 * @note (FIXME) This is left here for historical reasons. It belongs in the
 * output code. Besides, this operation should be avoided if possible.
 */
static block_t *aout_OutputSlice (audio_output_t *p_aout)
{
    aout_packet_t *p = aout_packet (p_aout);
    aout_fifo_t *p_fifo = &p->partial;
    const unsigned samples = p->samples;
    assert( samples > 0 );

    vlc_assert_locked( &p->lock );

    /* Retrieve the date of the next buffer. */
    date_t exact_start_date = p->fifo.end_date;
    mtime_t start_date = date_Get( &exact_start_date );

    /* See if we have enough data to prepare a new buffer for the audio output. */
    aout_buffer_t *p_buffer = p_fifo->p_first;
    if( p_buffer == NULL )
        return NULL;

    /* Find the earliest start date available. */
    if ( start_date == VLC_TS_INVALID )
    {
        start_date = p_buffer->i_pts;
        date_Set( &exact_start_date, start_date );
    }
    /* Compute the end date for the new buffer. */
    mtime_t end_date = date_Increment( &exact_start_date, samples );

    /* Check that we have enough samples (TODO merge with next loop). */
    for( unsigned available = 0; available < samples; )
    {
        p_buffer = p_buffer->p_next;
        if( p_buffer == NULL )
            return NULL;

        available += p_buffer->i_nb_samples;
    }

    if( AOUT_FMT_LINEAR( &p_aout->format ) )
    {
        const unsigned framesize = p_aout->format.i_bytes_per_frame;
        /* Build packet with adequate number of samples */
        unsigned needed = samples * framesize;

        p_buffer = block_Alloc( needed );
        if( unlikely(p_buffer == NULL) )
            /* XXX: should free input buffers */
            return NULL;
        p_buffer->i_nb_samples = samples;

        for( uint8_t *p_out = p_buffer->p_buffer; needed > 0; )
        {
            aout_buffer_t *p_inbuf = p_fifo->p_first;
            if( unlikely(p_inbuf == NULL) )
            {
                msg_Err( p_aout, "packetization error" );
                vlc_memset( p_out, 0, needed );
                break;
            }

            const uint8_t *p_in = p_inbuf->p_buffer;
            size_t avail = p_inbuf->i_nb_samples * framesize;
            if( avail > needed )
            {
                vlc_memcpy( p_out, p_in, needed );
                p_fifo->p_first->p_buffer += needed;
                p_fifo->p_first->i_buffer -= needed;
                needed /= framesize;
                p_fifo->p_first->i_nb_samples -= needed;

                mtime_t t = needed * CLOCK_FREQ / p_aout->format.i_rate;
                p_fifo->p_first->i_pts += t;
                p_fifo->p_first->i_length -= t;
                break;
            }

            vlc_memcpy( p_out, p_in, avail );
            needed -= avail;
            p_out += avail;
            /* Next buffer */
            aout_BufferFree( aout_FifoPop( p_fifo ) );
        }
    }
    else
        p_buffer = aout_FifoPop( p_fifo );

    p_buffer->i_pts = start_date;
    p_buffer->i_length = end_date - start_date;

    return p_buffer;
}
Exemple #12
0
/*****************************************************************************
 * Render: displays previously rendered output
 *****************************************************************************
 * This function send the currently rendered image to Distort image, waits
 * until it is displayed and switch the two rendering buffers, preparing next
 * frame.
 *****************************************************************************/
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
    picture_t *p_outpic;
    int i_index;
    double f_angle;
    mtime_t new_date = mdate();

    if( !p_pic ) return NULL;

    p_outpic = filter_NewPicture( p_filter );
    if( !p_outpic )
    {
        picture_Release( p_pic );
        return NULL;
    }

    p_filter->p_sys->f_angle -= (p_filter->p_sys->last_date - new_date) / 100000.0;
    p_filter->p_sys->last_date = new_date;
    f_angle = p_filter->p_sys->f_angle;

    for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
    {
        int i_line, i_first_line, i_num_lines, i_offset, i_pixel_pitch,
            i_visible_pixels;
        uint8_t black_pixel;
        uint8_t *p_in, *p_out;

        black_pixel = ( p_pic->i_planes > 1 && i_index == Y_PLANE ) ? 0x00
                                                                    : 0x80;

        i_num_lines = p_pic->p[i_index].i_visible_lines;
        i_pixel_pitch = p_pic->p[i_index].i_pixel_pitch;
        i_visible_pixels = p_pic->p[i_index].i_visible_pitch/p_pic->p[i_index].i_pixel_pitch;

        i_first_line = i_num_lines * 4 / 5;

        p_in = p_pic->p[i_index].p_pixels;
        p_out = p_outpic->p[i_index].p_pixels;

        for( i_line = 0 ; i_line < i_first_line ; i_line++ )
        {
            vlc_memcpy( p_out, p_in, p_pic->p[i_index].i_visible_pitch );
            p_in += p_pic->p[i_index].i_pitch;
            p_out += p_outpic->p[i_index].i_pitch;
        }

        /* Ok, we do 3 times the sin() calculation for each line. So what ? */
        for( i_line = i_first_line ; i_line < i_num_lines ; i_line++ )
        {
            /* Calculate today's offset, don't go above 1/20th of the screen */
            i_offset = (int)( (double)(i_visible_pixels)
                         * sin( f_angle + 2.0 * (double)i_line
                                              / (double)( 1 + i_line
                                                            - i_first_line) )
                         * (double)(i_line - i_first_line)
                         / (double)i_num_lines
                         / 8.0 )*p_pic->p[i_index].i_pixel_pitch;

            if( i_offset )
            {
                if( i_offset < 0 )
                {
                    vlc_memcpy( p_out, p_in - i_offset,
                                p_pic->p[i_index].i_visible_pitch + i_offset );
                    p_in -= p_pic->p[i_index].i_pitch;
                    p_out += p_outpic->p[i_index].i_pitch;
                    vlc_memset( p_out + i_offset, black_pixel, -i_offset );
                }
                else
                {
                    vlc_memcpy( p_out + i_offset, p_in,
                                p_pic->p[i_index].i_visible_pitch - i_offset );
                    vlc_memset( p_out, black_pixel, i_offset );
                    p_in -= p_pic->p[i_index].i_pitch;
                    p_out += p_outpic->p[i_index].i_pitch;
                }
            }
            else
            {
                vlc_memcpy( p_out, p_in, p_pic->p[i_index].i_visible_pitch );
                p_in -= p_pic->p[i_index].i_pitch;
                p_out += p_outpic->p[i_index].i_pitch;
            }

        }
    }

    return CopyInfoAndRelease( p_outpic, p_pic );
}
Exemple #13
0
/****************************************************************************
 * Filter: the whole thing
 ****************************************************************************/
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    picture_t *p_outpic;
    int i_plane;
    int i_width, i_height, i_xcrop, i_ycrop,
        i_outwidth, i_outheight, i_xpadd, i_ypadd;

    const int p_padd_color[] = { 0x00, 0x80, 0x80, 0xff };

    if( !p_pic ) return NULL;

    /* Request output picture */
    p_outpic = filter_NewPicture( p_filter );
    if( !p_outpic )
    {
        picture_Release( p_pic );
        return NULL;
    }

    for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
    /* p_pic and p_outpic have the same chroma/number of planes but that's
     * about it. */
    {
        plane_t *p_plane = p_pic->p+i_plane;
        plane_t *p_outplane = p_outpic->p+i_plane;
        uint8_t *p_in = p_plane->p_pixels;
        uint8_t *p_out = p_outplane->p_pixels;
        int i_pixel_pitch = p_plane->i_pixel_pitch;
        int i_padd_color = i_plane > 3 ? p_padd_color[0]
                                       : p_padd_color[i_plane];

        /* These assignments assume that the first plane always has
         * a width and height equal to the picture's */
        i_width =     ( ( p_filter->fmt_in.video.i_visible_width
                          - p_sys->i_cropleft - p_sys->i_cropright )
                        * p_plane->i_visible_pitch )
                      / p_pic->p->i_visible_pitch;
        i_height =    ( ( p_filter->fmt_in.video.i_visible_height
                          - p_sys->i_croptop - p_sys->i_cropbottom )
                        * p_plane->i_visible_lines )
                      / p_pic->p->i_visible_lines;
        i_xcrop =     ( p_sys->i_cropleft * p_plane->i_visible_pitch)
                      / p_pic->p->i_visible_pitch;
        i_ycrop =     ( p_sys->i_croptop * p_plane->i_visible_lines)
                      / p_pic->p->i_visible_lines;
        i_outwidth =  ( p_filter->fmt_out.video.i_visible_width
                        * p_outplane->i_visible_pitch )
                      / p_outpic->p->i_visible_pitch;
        i_outheight = ( p_filter->fmt_out.video.i_visible_height
                        * p_outplane->i_visible_lines )
                      / p_outpic->p->i_visible_lines;
        i_xpadd =     ( p_sys->i_paddleft * p_outplane->i_visible_pitch )
                      / p_outpic->p->i_visible_pitch;
        i_ypadd =     ( p_sys->i_paddtop * p_outplane->i_visible_lines )
                       / p_outpic->p->i_visible_lines;

        /* Crop the top */
        p_in += i_ycrop * p_plane->i_pitch;

        /* Padd on the top */
        vlc_memset( p_out, i_padd_color, i_ypadd * p_outplane->i_pitch );
        p_out += i_ypadd * p_outplane->i_pitch;

        int i_line;
        for( i_line = 0; i_line < i_height; i_line++ )
        {
            uint8_t *p_in_next = p_in + p_plane->i_pitch;
            uint8_t *p_out_next = p_out + p_outplane->i_pitch;

            /* Crop on the left */
            p_in += i_xcrop * i_pixel_pitch;

            /* Padd on the left */
            vlc_memset( p_out, i_padd_color, i_xpadd * i_pixel_pitch );
            p_out += i_xpadd * i_pixel_pitch;

            /* Copy the image and crop on the right */
            vlc_memcpy( p_out, p_in, i_width * i_pixel_pitch );
            p_out += i_width * i_pixel_pitch;
            p_in += i_width * i_pixel_pitch;

            /* Padd on the right */
            vlc_memset( p_out, i_padd_color,
                        ( i_outwidth - i_xpadd - i_width ) * i_pixel_pitch );

            /* Got to begining of the next line */
            p_in = p_in_next;
            p_out = p_out_next;
        }

        /* Padd on the bottom */
        vlc_memset( p_out, i_padd_color,
                 ( i_outheight - i_ypadd - i_height ) * p_outplane->i_pitch );
    }

    return CopyInfoAndRelease( p_outpic, p_pic );
}
/**
 * It filters a video plane
 */
static void FilterPlanar( uint8_t *p_out, int i_out_pitch,
                          const uint8_t *p_in, int i_in_pitch,
                          int i_copy_pitch,
                          int i_copy_lines,
                          int i_pixel_black,
                          const panoramix_filter_t *p_cfg,
                          uint8_t p_lut[ACCURACY + 1][256],
                          int lambdav[2][ACCURACY/2],
                          int lambdah[2][ACCURACY/2] )
{
    /* */
    assert( !p_cfg->black.i_left   || !p_cfg->attenuate.i_left );
    assert( !p_cfg->black.i_right  || !p_cfg->attenuate.i_right );
    assert( !p_cfg->black.i_top    || !p_cfg->attenuate.i_top );
    assert( !p_cfg->black.i_bottom || !p_cfg->attenuate.i_bottom );

    const int i_out_width = p_cfg->black.i_left + i_copy_pitch + p_cfg->black.i_right;

    /* Top black border */
    for( int b = 0; b < p_cfg->black.i_top; b++ )
    {
        vlc_memset( p_out, i_pixel_black, i_out_width );
        p_out += i_out_pitch;
    }

    for( int y = 0; y < i_copy_lines; y++ )
    {
        const uint8_t *p_src = p_in;
        uint8_t *p_dst = p_out;

        /* Black border on the left */
        if( p_cfg->black.i_left > 0 )
        {
            memset( p_dst, i_pixel_black, p_cfg->black.i_left );
            p_dst += p_cfg->black.i_left;
        }
        /* Attenuated video on the left */
        for( int i = 0; i < p_cfg->attenuate.i_left; i++ )
            *p_dst++ = p_lut[lambdav[0][i]][*p_src++];

        /* Unmodified video */
        const int i_unmodified_width = i_copy_pitch - p_cfg->attenuate.i_left - p_cfg->attenuate.i_right;
        vlc_memcpy( p_dst, p_src, i_unmodified_width );
        p_dst += i_unmodified_width;
        p_src += i_unmodified_width;

        /* Attenuated video on the right */
        for( int i = 0; i < p_cfg->attenuate.i_right; i++ )
            *p_dst++ = p_lut[lambdav[1][i]][*p_src++];
        /* Black border on the right */
        if( p_cfg->black.i_right > 0 )
        {
            memset( p_dst, i_pixel_black, p_cfg->black.i_right );
            p_dst += p_cfg->black.i_right;
        }

        /* Attenuate complete line at top/bottom */
        const bool b_attenuate_top    = y < p_cfg->attenuate.i_top;
        const bool b_attenuate_bottom = y >= i_copy_lines - p_cfg->attenuate.i_bottom;
        if( b_attenuate_top || b_attenuate_bottom )
        {
            const int i_index = b_attenuate_top ? lambdah[0][y] : lambdah[1][y - (i_copy_lines - p_cfg->attenuate.i_bottom)];
            uint8_t *p_dst = &p_out[0];
            for( int i = 0; i < i_out_width; i++)
                p_dst[i] = p_lut[i_index][p_dst[i]];
        }

        /* */
        p_in  += i_in_pitch;
        p_out += i_out_pitch;
    }
    /* Bottom black border */
    for( int b = 0; b < p_cfg->black.i_bottom; b++ )
    {
        vlc_memset( p_out, i_pixel_black, i_out_width );
        p_out += i_out_pitch;
    }
}