Exemple #1
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 #2
0
void RenderBlend( filter_t *p_filter,
                  picture_t *p_outpic, picture_t *p_pic )
{
    int i_plane;

    /* Copy image and skip lines */
    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
    {
        uint8_t *p_in, *p_out_end, *p_out;

        p_in = p_pic->p[i_plane].p_pixels;

        p_out = p_outpic->p[i_plane].p_pixels;
        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
                             * p_outpic->p[i_plane].i_visible_lines;

        switch( p_filter->fmt_in.video.i_chroma )
        {
            case VLC_CODEC_I420:
            case VLC_CODEC_J420:
            case VLC_CODEC_YV12:
                /* First line: simple copy */
                vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                p_out += p_outpic->p[i_plane].i_pitch;

                /* Remaining lines: mean value */
                for( ; p_out < p_out_end ; )
                {
                    Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
                           p_pic->p[i_plane].i_pitch );

                    p_out += p_outpic->p[i_plane].i_pitch;
                    p_in  += p_pic->p[i_plane].i_pitch;
                }
                break;

            case VLC_CODEC_I422:
            case VLC_CODEC_J422:
                /* First line: simple copy */
                vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                p_out += p_outpic->p[i_plane].i_pitch;

                /* Remaining lines: mean value */
                if( i_plane == Y_PLANE )
                {
                    for( ; p_out < p_out_end ; )
                    {
                        Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
                               p_pic->p[i_plane].i_pitch );

                        p_out += p_outpic->p[i_plane].i_pitch;
                        p_in  += p_pic->p[i_plane].i_pitch;
                    }
                }
                else
                {
                    for( ; p_out < p_out_end ; )
                    {
                        Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
                               p_pic->p[i_plane].i_pitch );

                        p_out += p_outpic->p[i_plane].i_pitch;
                        p_in  += 2*p_pic->p[i_plane].i_pitch;
                    }
                }
                break;
        }
    }
    EndMerge();
}
Exemple #3
0
void RenderDiscard( filter_t *p_filter,
                    picture_t *p_outpic, picture_t *p_pic, int i_field )
{
    int i_plane;

    /* Copy image and skip lines */
    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
    {
        uint8_t *p_in, *p_out_end, *p_out;
        int i_increment;

        p_in = p_pic->p[i_plane].p_pixels
                   + i_field * p_pic->p[i_plane].i_pitch;

        p_out = p_outpic->p[i_plane].p_pixels;
        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
                             * p_outpic->p[i_plane].i_visible_lines;

        switch( p_filter->fmt_in.video.i_chroma )
        {
        case VLC_CODEC_I420:
        case VLC_CODEC_J420:
        case VLC_CODEC_YV12:

            for( ; p_out < p_out_end ; )
            {
                vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                p_out += p_outpic->p[i_plane].i_pitch;
                p_in += 2 * p_pic->p[i_plane].i_pitch;
            }
            break;

        case VLC_CODEC_I422:
        case VLC_CODEC_J422:

            i_increment = 2 * p_pic->p[i_plane].i_pitch;

            if( i_plane == Y_PLANE )
            {
                for( ; p_out < p_out_end ; )
                {
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                    p_out += p_outpic->p[i_plane].i_pitch;
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                    p_out += p_outpic->p[i_plane].i_pitch;
                    p_in += i_increment;
                }
            }
            else
            {
                for( ; p_out < p_out_end ; )
                {
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                    p_out += p_outpic->p[i_plane].i_pitch;
                    p_in += i_increment;
                }
            }
            break;

        default:
            break;
        }
    }
}
Exemple #4
0
/*****************************************************************************
 * DoWork: convert a buffer
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
    float *p_out = (float *)p_out_buf->p_buffer;

    int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
    int i_in_nb = p_in_buf->i_nb_samples;
    int i_in, i_out = 0;
    unsigned int i_out_rate;
    double d_factor, d_scale_factor, d_old_scale_factor;
    int i_filter_wing;

    if( p_sys->b_filter2 )
        i_out_rate = p_filter->output.i_rate;
    else
        i_out_rate = p_aout->mixer_format.i_rate;

    /* Check if we really need to run the resampler */
    if( i_out_rate == p_filter->input.i_rate )
    {
        if( /*p_filter->b_continuity && /--* What difference does it make ? :) */
            p_sys->i_old_wing &&
            p_in_buf->i_size >=
              p_in_buf->i_nb_bytes + p_sys->i_old_wing *
              p_filter->input.i_bytes_per_frame )
        {
            /* output the whole thing with the samples from last time */
            memmove( ((float *)(p_in_buf->p_buffer)) +
                     i_nb_channels * p_sys->i_old_wing,
                     p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
            memcpy( p_in_buf->p_buffer, p_sys->p_buf +
                    i_nb_channels * p_sys->i_old_wing,
                    p_sys->i_old_wing *
                    p_filter->input.i_bytes_per_frame );

            p_out_buf->i_nb_samples = p_in_buf->i_nb_samples +
                p_sys->i_old_wing;

            p_out_buf->start_date = date_Get( &p_sys->end_date );
            p_out_buf->end_date =
                date_Increment( &p_sys->end_date,
                                p_out_buf->i_nb_samples );

            p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
                p_filter->input.i_bytes_per_frame;
        }
        p_filter->b_continuity = false;
        p_sys->i_old_wing = 0;
        return;
    }

    if( !p_filter->b_continuity )
    {
        /* Continuity in sound samples has been broken, we'd better reset
         * everything. */
        p_filter->b_continuity = true;
        p_sys->i_remainder = 0;
        date_Init( &p_sys->end_date, i_out_rate, 1 );
        date_Set( &p_sys->end_date, p_in_buf->start_date );
        p_sys->i_old_rate   = p_filter->input.i_rate;
        p_sys->d_old_factor = 1;
        p_sys->i_old_wing   = 0;
    }

#if 0
    msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
             p_sys->i_old_rate, p_sys->d_old_factor,
             p_sys->i_old_wing, i_in_nb );
#endif

    /* Prepare the source buffer */
    i_in_nb += (p_sys->i_old_wing * 2);

    float p_in_orig[i_in_nb * p_filter->input.i_bytes_per_frame / 4],
         *p_in = p_in_orig;

    /* Copy all our samples in p_in */
    if( p_sys->i_old_wing )
    {
        vlc_memcpy( p_in, p_sys->p_buf,
                    p_sys->i_old_wing * 2 *
                      p_filter->input.i_bytes_per_frame );
    }
    vlc_memcpy( p_in + p_sys->i_old_wing * 2 * i_nb_channels,
                p_in_buf->p_buffer,
                p_in_buf->i_nb_samples * p_filter->input.i_bytes_per_frame );

    /* Make sure the output buffer is reset */
    memset( p_out, 0, p_out_buf->i_size );

    /* Calculate the new length of the filter wing */
    d_factor = (double)i_out_rate / p_filter->input.i_rate;
    i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1;

    /* Account for increased filter gain when using factors less than 1 */
    d_old_scale_factor = SMALL_FILTER_SCALE *
        p_sys->d_old_factor + 0.5;
    d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5;

    /* Apply the old rate until we have enough samples for the new one */
    i_in = p_sys->i_old_wing;
    p_in += p_sys->i_old_wing * i_nb_channels;
    for( ; i_in < i_filter_wing &&
           (i_in + p_sys->i_old_wing) < i_in_nb; i_in++ )
    {
        if( p_sys->d_old_factor == 1 )
        {
            /* Just copy the samples */
            memcpy( p_out, p_in,
                    p_filter->input.i_bytes_per_frame );
            p_in += i_nb_channels;
            p_out += i_nb_channels;
            i_out++;
            continue;
        }

        while( p_sys->i_remainder < p_filter->output.i_rate )
        {

            if( p_sys->d_old_factor >= 1 )
            {
                /* FilterFloatUP() is faster if we can use it */

                /* Perform left-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->output.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->output.i_rate -
                               p_sys->i_remainder,
                               p_filter->output.i_rate,
                               1, i_nb_channels );

#if 0
                /* Normalize for unity filter gain */
                for( i = 0; i < i_nb_channels; i++ )
                {
                    *(p_out+i) *= d_old_scale_factor;
                }
#endif

                /* Sanity check */
                if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
                    <= (unsigned int)i_out+1 )
                {
                    p_out += i_nb_channels;
                    i_out++;
                    p_sys->i_remainder += p_filter->input.i_rate;
                    break;
                }
            }
            else
            {
                /* Perform left-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->output.i_rate, p_filter->input.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->output.i_rate -
                               p_sys->i_remainder,
                               p_filter->output.i_rate, p_filter->input.i_rate,
                               1, i_nb_channels );
            }

            p_out += i_nb_channels;
            i_out++;

            p_sys->i_remainder += p_filter->input.i_rate;
        }

        p_in += i_nb_channels;
        p_sys->i_remainder -= p_filter->output.i_rate;
    }

    /* Apply the new rate for the rest of the samples */
    if( i_in < i_in_nb - i_filter_wing )
    {
        p_sys->i_old_rate   = p_filter->input.i_rate;
        p_sys->d_old_factor = d_factor;
        p_sys->i_old_wing   = i_filter_wing;
    }
    for( ; i_in < i_in_nb - i_filter_wing; i_in++ )
    {
        while( p_sys->i_remainder < p_filter->output.i_rate )
        {

            if( d_factor >= 1 )
            {
                /* FilterFloatUP() is faster if we can use it */

                /* Perform left-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->output.i_rate,
                               -1, i_nb_channels );

                /* Perform right-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->output.i_rate -
                               p_sys->i_remainder,
                               p_filter->output.i_rate,
                               1, i_nb_channels );

#if 0
                /* Normalize for unity filter gain */
                for( int i = 0; i < i_nb_channels; i++ )
                {
                    *(p_out+i) *= d_old_scale_factor;
                }
#endif
                /* Sanity check */
                if( p_out_buf->i_size/p_filter->input.i_bytes_per_frame
                    <= (unsigned int)i_out+1 )
                {
                    p_out += i_nb_channels;
                    i_out++;
                    p_sys->i_remainder += p_filter->input.i_rate;
                    break;
                }
            }
            else
            {
                /* Perform left-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->output.i_rate, p_filter->input.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->output.i_rate -
                               p_sys->i_remainder,
                               p_filter->output.i_rate, p_filter->input.i_rate,
                               1, i_nb_channels );
            }

            p_out += i_nb_channels;
            i_out++;

            p_sys->i_remainder += p_filter->input.i_rate;
        }

        p_in += i_nb_channels;
        p_sys->i_remainder -= p_filter->output.i_rate;
    }

    /* Buffer i_filter_wing * 2 samples for next time */
    if( p_sys->i_old_wing )
    {
        memcpy( p_sys->p_buf,
                p_in_orig + (i_in_nb - 2 * p_sys->i_old_wing) *
                i_nb_channels, (2 * p_sys->i_old_wing) *
                p_filter->input.i_bytes_per_frame );
    }

#if 0
    msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_size,
             i_out * p_filter->input.i_bytes_per_frame );
#endif

    /* Finalize aout buffer */
    p_out_buf->i_nb_samples = i_out;
    p_out_buf->start_date = date_Get( &p_sys->end_date );
    p_out_buf->end_date = date_Increment( &p_sys->end_date,
                                          p_out_buf->i_nb_samples );

    p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
        i_nb_channels * sizeof(int32_t);

}
Exemple #5
0
void RenderBob( filter_t *p_filter,
                picture_t *p_outpic, picture_t *p_pic, int i_field )
{
    int i_plane;

    /* Copy image and skip lines */
    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
    {
        uint8_t *p_in, *p_out_end, *p_out;

        p_in = p_pic->p[i_plane].p_pixels;
        p_out = p_outpic->p[i_plane].p_pixels;
        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
                             * p_outpic->p[i_plane].i_visible_lines;

        switch( p_filter->fmt_in.video.i_chroma )
        {
            case VLC_CODEC_I420:
            case VLC_CODEC_J420:
            case VLC_CODEC_YV12:
                /* For BOTTOM field we need to add the first line */
                if( i_field == 1 )
                {
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                    p_in += p_pic->p[i_plane].i_pitch;
                    p_out += p_outpic->p[i_plane].i_pitch;
                }

                p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;

                for( ; p_out < p_out_end ; )
                {
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                    p_out += p_outpic->p[i_plane].i_pitch;

                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                    p_in += 2 * p_pic->p[i_plane].i_pitch;
                    p_out += p_outpic->p[i_plane].i_pitch;
                }

                vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                /* For TOP field we need to add the last line */
                if( i_field == 0 )
                {
                    p_in += p_pic->p[i_plane].i_pitch;
                    p_out += p_outpic->p[i_plane].i_pitch;
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                }
                break;

            case VLC_CODEC_I422:
            case VLC_CODEC_J422:
                /* For BOTTOM field we need to add the first line */
                if( i_field == 1 )
                {
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                    p_in += p_pic->p[i_plane].i_pitch;
                    p_out += p_outpic->p[i_plane].i_pitch;
                }

                p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;

                if( i_plane == Y_PLANE )
                {
                    for( ; p_out < p_out_end ; )
                    {
                        vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                        p_out += p_outpic->p[i_plane].i_pitch;

                        vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                        p_in += 2 * p_pic->p[i_plane].i_pitch;
                        p_out += p_outpic->p[i_plane].i_pitch;
                    }
                }
                else
                {
                    for( ; p_out < p_out_end ; )
                    {
                        vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                        p_out += p_outpic->p[i_plane].i_pitch;
                        p_in += 2 * p_pic->p[i_plane].i_pitch;
                    }
                }

                vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );

                /* For TOP field we need to add the last line */
                if( i_field == 0 )
                {
                    p_in += p_pic->p[i_plane].i_pitch;
                    p_out += p_outpic->p[i_plane].i_pitch;
                    vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
                }
                break;
        }
    }
}
Exemple #6
0
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;

    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;

    if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        block_Release( p_block );
        return NULL;
    }

    /* Remove ADTS header if we have decoder specific config */
    if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 )
    {
        if( p_block->p_buffer[0] == 0xff &&
            ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */
        {   /* ADTS header present */
            size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */
            i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 );
            /* FIXME: multiple blocks per frame */
            if( p_block->i_buffer > i_header_size )
            {
                p_block->p_buffer += i_header_size;
                p_block->i_buffer -= i_header_size;
            }
        }
    }

    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
        size_t  i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
        uint8_t *p_buffer     = realloc( p_sys->p_buffer, i_buffer_size );
        if( p_buffer )
        {
            p_sys->i_buffer_size = i_buffer_size;
            p_sys->p_buffer      = p_buffer;
        }
        else
        {
            p_block->i_buffer = 0;
        }
    }

    if( p_block->i_buffer > 0 )
    {
        vlc_memcpy( &p_sys->p_buffer[p_sys->i_buffer],
                     p_block->p_buffer, p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
                          &i_rate, &i_channels ) >= 0 )
        {
            p_dec->fmt_out.audio.i_rate = i_rate;
            p_dec->fmt_out.audio.i_channels = i_channels;
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[i_channels];

            date_Init( &p_sys->date, i_rate, 1 );
        }
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
    {
        unsigned long i_rate;
        unsigned char i_channels;

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
            block_Release( p_block );
            return NULL;
        }

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
        date_Init( &p_sys->date, i_rate, 1 );
    }

    if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != date_Get( &p_sys->date ) )
    {
        date_Set( &p_sys->date, p_block->i_pts );
    }
    else if( !date_Get( &p_sys->date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        p_sys->i_buffer = 0;
        return NULL;
    }

    /* Decode all data */
    if( p_sys->i_buffer )
    {
        void *samples;
        faacDecFrameInfo frame;
        aout_buffer_t *p_out;
        int i, j;

        samples = faacDecDecode( p_sys->hfaad, &frame,
                                 p_sys->p_buffer, p_sys->i_buffer );

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );

            if( frame.error == 21 )
            {
                /*
                 * Once an "Unexpected channel configuration change" error
                 * occurs, it will occurs afterwards, and we got no sound.
                 * Reinitialization of the decoder is required.
                 */
                unsigned long i_rate;
                unsigned char i_channels;
                faacDecHandle *hfaad;
                faacDecConfiguration *cfg,*oldcfg;

                oldcfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
                hfaad = faacDecOpen();
                cfg = faacDecGetCurrentConfiguration( hfaad );
                if( oldcfg->defSampleRate )
                    cfg->defSampleRate = oldcfg->defSampleRate;
                cfg->defObjectType = oldcfg->defObjectType;
                cfg->outputFormat = oldcfg->outputFormat;
                faacDecSetConfiguration( hfaad, cfg );

                if( faacDecInit( hfaad, p_sys->p_buffer, p_sys->i_buffer,
                                &i_rate,&i_channels ) < 0 )
                {
                    /* reinitialization failed */
                    faacDecClose( hfaad );
                    faacDecSetConfiguration( p_sys->hfaad, oldcfg );
                }
                else
                {
                    faacDecClose( p_sys->hfaad );
                    p_sys->hfaad = hfaad;
                    p_dec->fmt_out.audio.i_rate = i_rate;
                    p_dec->fmt_out.audio.i_channels = i_channels;
                    p_dec->fmt_out.audio.i_physical_channels
                        = p_dec->fmt_out.audio.i_original_channels
                        = pi_channels_guessed[i_channels];
                    date_Init( &p_sys->date, i_rate, 1 );
                }
            }

            /* Flush the buffer */
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
        {
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        if( frame.samples <= 0 )
        {
            msg_Warn( p_dec, "decoded zero sample" );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
        {
            date_Init( &p_sys->date, frame.samplerate, 1 );
            date_Set( &p_sys->date, p_block->i_pts );
        }
        p_block->i_pts = VLC_TS_INVALID;  /* PTS is valid only once */

        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[frame.channels];

        /* Adjust stream info when dealing with SBR/PS */
        bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2);
        if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps )
        {
            const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" :
                                    b_sbr ? "SBR" : "PS";

            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                    psz_ext, frame.channels, frame.samplerate );

            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            if( p_dec->p_description )
                vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext );

            p_sys->b_sbr = b_sbr;
            p_sys->b_ps = frame.ps;
        }

        /* Convert frame.channel_position to our own channel values */
        p_dec->fmt_out.audio.i_physical_channels = 0;
        for( i = 0; i < frame.channels; i++ )
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
            if( j >= MAX_CHANNEL_POSITIONS )
            {
                msg_Warn( p_dec, "unknown channel ordering" );
                /* Invent something */
                j = i;
            }
            /* */
            p_sys->pi_channel_positions[i] = pi_channels_out[j];
            if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] )
                frame.channels--; /* We loose a duplicated channel */
            else
                p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j];
        }
        p_dec->fmt_out.audio.i_original_channels =
            p_dec->fmt_out.audio.i_physical_channels;

        p_out = decoder_NewAudioBuffer(p_dec, frame.samples/frame.channels);
        if( p_out == NULL )
        {
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        p_out->i_pts = date_Get( &p_sys->date );
        p_out->i_length = date_Increment( &p_sys->date,
                                          frame.samples / frame.channels )
                          - p_out->i_pts;

        DoReordering( (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );

        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
        {
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
        }

        return p_out;
    }

    block_Release( p_block );
    return NULL;
}
/**
 * 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;
    }
}
Exemple #8
0
/*****************************************************************************
 * VideoGetBuffer: Build an alternate video buffer
 *****************************************************************************/
static block_t *VideoGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,
                                block_t *p_buffer )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    int i_out;
    block_t *p_out;

    id->p_frame->quality = p_sys->i_qscale * powf(2.0, FF_LAMBDA_SHIFT + 7.0)
                            / 139.0;
    id->p_frame->interlaced_frame = 0;
    id->p_frame->top_field_first = 1;
    id->p_frame->pts = p_buffer->i_dts;

    if ( id->i_nb_pred >= p_sys->i_gop )
    {
        id->p_frame->pict_type = FF_I_TYPE;
#if 0
        id->p_frame->me_threshold = 0;
        id->p_frame->mb_threshold = 0;
#endif
        id->i_nb_pred = 0;
    }
    else
    {
        id->p_frame->pict_type = FF_P_TYPE;
#if 0
        if ( id->p_frame->mb_type != NULL )
        {
            id->p_frame->me_threshold = MAX_THRESHOLD;
            id->p_frame->mb_threshold = MAX_THRESHOLD;
        }
#endif
        id->i_nb_pred++;
    }

    i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer_out,
                                  id->ff_enc_c->width * id->ff_enc_c->height * 3,
                                  id->p_frame );

    if ( i_out <= 0 )
        return NULL;

#if 0
    if ( id->p_frame->mb_type == NULL
          && id->ff_enc_c->coded_frame->pict_type != FF_I_TYPE )
    {
        int mb_width = (id->ff_enc_c->width + 15) / 16;
        int mb_height = (id->ff_enc_c->height + 15) / 16;
        int h_chroma_shift, v_chroma_shift;
        int i;

        avcodec_get_chroma_sub_sample( id->ff_enc_c->pix_fmt, &h_chroma_shift,
                                       &v_chroma_shift );

        id->p_frame->motion_subsample_log2
            = id->ff_enc_c->coded_frame->motion_subsample_log2;
        id->p_frame->mb_type = malloc( ((mb_width + 1) * (mb_height + 1) + 1)
                                    * sizeof(uint32_t) );
        vlc_memcpy( id->p_frame->mb_type, id->ff_enc_c->coded_frame->mb_type,
                    (mb_width + 1) * mb_height * sizeof(id->p_frame->mb_type[0]));

        for ( i = 0; i < 2; i++ )
        {
            int stride = ((16 * mb_width )
                    >> id->ff_enc_c->coded_frame->motion_subsample_log2) + 1;
            int height = ((16 * mb_height)
                    >> id->ff_enc_c->coded_frame->motion_subsample_log2);
            int b8_stride = mb_width * 2 + 1;

            if ( id->ff_enc_c->coded_frame->motion_val[i] )
            {
                id->p_frame->motion_val[i] = malloc( 2 * stride * height
                                                * sizeof(int16_t) );
                vlc_memcpy( id->p_frame->motion_val[i],
                            id->ff_enc_c->coded_frame->motion_val[i],
                            2 * stride * height * sizeof(int16_t) );
            }
            if ( id->ff_enc_c->coded_frame->ref_index[i] )
            {
                id->p_frame->ref_index[i] = malloc( b8_stride * 2 * mb_height
                                               * sizeof(int8_t) );
                vlc_memcpy( id->p_frame->ref_index[i],
                            id->ff_enc_c->coded_frame->ref_index[i],
                            b8_stride * 2 * mb_height * sizeof(int8_t));
            }
        }
    }
Exemple #9
0
/*****************************************************************************
 * DoWork: decode an MPEG audio frame.
 *****************************************************************************/
static void DoWork( filter_t * p_filter,
                    block_t * p_in_buf, block_t * p_out_buf )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(vlc_fixed_t) *
                               aout_FormatNbChannels( &p_filter->fmt_out.audio );

    /* Do the actual decoding now. */
    mad_stream_buffer( &p_sys->mad_stream, p_in_buf->p_buffer,
                       p_in_buf->i_buffer );
    if ( mad_frame_decode( &p_sys->mad_frame, &p_sys->mad_stream ) == -1 )
    {
        msg_Dbg( p_filter, "libmad error: %s",
                  mad_stream_errorstr( &p_sys->mad_stream ) );
        p_sys->i_reject_count = 3;
    }
    else if( p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        p_sys->i_reject_count = 3;
    }

    if( p_sys->i_reject_count > 0 )
    {
        if( p_filter->fmt_out.audio.i_format == VLC_CODEC_FL32 )
        {
            int i;
            int i_size = p_out_buf->i_buffer / sizeof(float);

            float * a = (float *)p_out_buf->p_buffer;
            for ( i = 0 ; i < i_size ; i++ )
                *a++ = 0.0;
        }
        else
        {
            memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
        }
        p_sys->i_reject_count--;
        return;
    }


    mad_synth_frame( &p_sys->mad_synth, &p_sys->mad_frame );

    struct mad_pcm * p_pcm = &p_sys->mad_synth.pcm;
    unsigned int i_samples = p_pcm->length;
    mad_fixed_t const * p_left = p_pcm->samples[0];
    mad_fixed_t const * p_right = p_pcm->samples[1];

    assert( i_samples == p_out_buf->i_nb_samples );
    if ( p_filter->fmt_out.audio.i_format == VLC_CODEC_FI32 )
    {
        /* Interleave and keep buffers in mad_fixed_t format */
        mad_fixed_t * p_samples = (mad_fixed_t *)p_out_buf->p_buffer;

        if ( p_pcm->channels == 2 )
        {
            while ( i_samples-- )
            {
                *p_samples++ = *p_left++;
                *p_samples++ = *p_right++;
            }
        }
        else
        {
            assert( p_pcm->channels == 1 );
            vlc_memcpy( p_samples, p_left, i_samples * sizeof(mad_fixed_t) );
        }
    }
    else
    {
        /* float32 */
        float * p_samples = (float *)p_out_buf->p_buffer;
        const float f_temp = (float)FIXED32_ONE;

        if ( p_pcm->channels == 2 )
        {
            while ( i_samples-- )
            {
                *p_samples++ = (float)*p_left++ / f_temp;
                *p_samples++ = (float)*p_right++ / f_temp;
            }
        }
        else
        {
            assert( p_pcm->channels == 1 );
            while ( i_samples-- )
            {
                *p_samples++ = (float)*p_left++ / f_temp;
            }
        }
    }
}
int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
                 int i_order, int i_field )
{
    VLC_UNUSED(p_src);

    filter_sys_t *p_sys = p_filter->p_sys;

    /* */
    assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */
    assert( i_field == 0 || i_field == 1 );

    /* As the pitches must match, use ONLY pictures coming from picture_New()! */
    picture_t *p_prev = p_sys->pp_history[0];
    picture_t *p_cur  = p_sys->pp_history[1];
    picture_t *p_next = p_sys->pp_history[2];

    /* Account for soft field repeat.

       The "parity" parameter affects the algorithm like this (from yadif.h):
       uint8_t *prev2= parity ? prev : cur ;
       uint8_t *next2= parity ? cur  : next;

       The original parity expression that was used here is:
       (i_field ^ (i_order == i_field)) & 1

       Truth table:
       i_field = 0, i_order = 0  => 1
       i_field = 1, i_order = 1  => 0
       i_field = 1, i_order = 0  => 1
       i_field = 0, i_order = 1  => 0

       => equivalent with e.g.  (1 - i_order)  or  (i_order + 1) % 2

       Thus, in a normal two-field frame,
             parity 1 = first field  (i_order == 0)
             parity 0 = second field (i_order == 1)

       Now, with three fields, where the third is a copy of the first,
             i_order = 0  =>  parity 1 (as usual)
             i_order = 1  =>  due to the repeat, prev = cur, but also next = cur.
                              Because in such a case there is no motion
                              (otherwise field repeat makes no sense),
                              we don't actually need to invoke Yadif's filter().
                              Thus, set "parity" to 2, and use this to bypass
                              the filter.
             i_order = 2  =>  parity 0 (as usual)
    */
    int yadif_parity;
    if( p_cur  &&  p_cur->i_nb_fields > 2 )
        yadif_parity = (i_order + 1) % 3; /* 1, *2*, 0; where 2 is a special
                                             value meaning "bypass filter". */
    else
        yadif_parity = (i_order + 1) % 2; /* 1, 0 */

    /* Filter if we have all the pictures we need */
    if( p_prev && p_cur && p_next )
    {
        /* */
        void (*filter)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next,
                       int w, int prefs, int mrefs, int parity, int mode);

        filter = yadif_filter_line_c;
#if defined(HAVE_YADIF_MMX)
        if( vlc_CPU() & CPU_CAPABILITY_MMX )
            filter = yadif_filter_line_mmx;
#endif
#if defined(HAVE_YADIF_SSE2)
        if( vlc_CPU() & CPU_CAPABILITY_SSE2 )
            filter = yadif_filter_line_sse2;
#endif
#if defined(HAVE_YADIF_SSSE3)
        if( vlc_CPU() & CPU_CAPABILITY_SSSE3 )
            filter = yadif_filter_line_ssse3;
#endif

        for( int n = 0; n < p_dst->i_planes; n++ )
        {
            const plane_t *prevp = &p_prev->p[n];
            const plane_t *curp  = &p_cur->p[n];
            const plane_t *nextp = &p_next->p[n];
            plane_t *dstp        = &p_dst->p[n];

            for( int y = 1; y < dstp->i_visible_lines - 1; y++ )
            {
                if( (y % 2) == i_field  ||  yadif_parity == 2 )
                {
                    vlc_memcpy( &dstp->p_pixels[y * dstp->i_pitch],
                                &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch );
                }
                else
                {
                    int mode;
                    /* Spatial checks only when enough data */
                    mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2;

                    assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch );
                    filter( &dstp->p_pixels[y * dstp->i_pitch],
                            &prevp->p_pixels[y * prevp->i_pitch],
                            &curp->p_pixels[y * curp->i_pitch],
                            &nextp->p_pixels[y * nextp->i_pitch],
                            dstp->i_visible_pitch,
                            y < dstp->i_visible_lines - 2  ? curp->i_pitch : -curp->i_pitch,
                            y  - 1  ?  -curp->i_pitch : curp->i_pitch,
                            yadif_parity,
                            mode );
                }

                /* We duplicate the first and last lines */
                if( y == 1 )
                    vlc_memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch],
                               &dstp->p_pixels[ y    * dstp->i_pitch],
                               dstp->i_pitch);
                else if( y == dstp->i_visible_lines - 2 )
                    vlc_memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch],
                               &dstp->p_pixels[ y    * dstp->i_pitch],
                               dstp->i_pitch);
            }
        }

        p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */

        return VLC_SUCCESS;
    }
    else if( !p_prev && !p_cur && p_next )
    {
        /* NOTE: For the first frame, we use the default frame offset
                 as set by Open() or SetFilterMethod(). It is always 0. */

        /* FIXME not good as it does not use i_order/i_field */
        RenderX( p_dst, p_next );
        return VLC_SUCCESS;
    }
    else
    {
        p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */

        return VLC_EGENERIC;
    }
}
Exemple #11
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************
 * This function must be fed with a complete compressed frame.
 ****************************************************************************/
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;
    picture_t *p_pic = NULL;
    SDL_Surface *p_surface;
    SDL_RWops *p_rw;

    if( pp_block == NULL || *pp_block == NULL ) return NULL;
    p_block = *pp_block;

    if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_rw = SDL_RWFromConstMem( p_block->p_buffer, p_block->i_buffer );

    /* Decode picture. */
    p_surface = IMG_LoadTyped_RW( p_rw, 1, (char*)p_sys->psz_sdl_type );
    if ( p_surface == NULL )
    {
        msg_Warn( p_dec, "SDL_image couldn't load the image (%s)",
                  IMG_GetError() );
        goto error;
    }

    switch ( p_surface->format->BitsPerPixel )
    {
    case 16:
        p_dec->fmt_out.i_codec = VLC_CODEC_RGB16;
        break;
    case 8:
    case 24:
        p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
        break;
    case 32:
        p_dec->fmt_out.i_codec = VLC_CODEC_RGB32;
        break;
    default:
        msg_Warn( p_dec, "unknown bits/pixel format (%d)",
                  p_surface->format->BitsPerPixel );
        goto error;
    }
    p_dec->fmt_out.video.i_width = p_surface->w;
    p_dec->fmt_out.video.i_height = p_surface->h;
    p_dec->fmt_out.video.i_sar_num = 1;
    p_dec->fmt_out.video.i_sar_den = 1;

    /* Get a new picture. */
    p_pic = decoder_NewPicture( p_dec );
    if ( p_pic == NULL ) goto error;

    switch ( p_surface->format->BitsPerPixel )
    {
        case 8:
        {
            int i, j;
            uint8_t *p_src, *p_dst;
            uint8_t r, g, b;
            for ( i = 0; i < p_surface->h; i++ )
            {
                p_src = (uint8_t*)p_surface->pixels + i * p_surface->pitch;
                p_dst = p_pic->p[0].p_pixels + i * p_pic->p[0].i_pitch;
                for ( j = 0; j < p_surface->w; j++ )
                {
                    SDL_GetRGB( *(p_src++), p_surface->format,
                                &r, &g, &b );
                    *(p_dst++) = r;
                    *(p_dst++) = g;
                    *(p_dst++) = b;
                }
            }
            break;
        }
        case 16:
        {
            int i;
            uint8_t *p_src = p_surface->pixels;
            uint8_t *p_dst = p_pic->p[0].p_pixels;
            int i_pitch = p_pic->p[0].i_pitch < p_surface->pitch ?
                p_pic->p[0].i_pitch : p_surface->pitch;

            for ( i = 0; i < p_surface->h; i++ )
            {
                vlc_memcpy( p_dst, p_src, i_pitch );
                p_src += p_surface->pitch;
                p_dst += p_pic->p[0].i_pitch;
            }
            break;
        }
        case 24:
        {
            int i, j;
            uint8_t *p_src, *p_dst;
            uint8_t r, g, b;
            for ( i = 0; i < p_surface->h; i++ )
            {
                p_src = (uint8_t*)p_surface->pixels + i * p_surface->pitch;
                p_dst = p_pic->p[0].p_pixels + i * p_pic->p[0].i_pitch;
                for ( j = 0; j < p_surface->w; j++ )
                {
                    SDL_GetRGB( *(uint32_t*)p_src, p_surface->format,
                                &r, &g, &b );
                    *(p_dst++) = r;
                    *(p_dst++) = g;
                    *(p_dst++) = b;
                    p_src += 3;
                }
            }
            break;
        }
        case 32:
        {
            int i, j;
            uint8_t *p_src, *p_dst;
            uint8_t r, g, b, a;
            for ( i = 0; i < p_surface->h; i++ )
            {
                p_src = (uint8_t*)p_surface->pixels + i * p_surface->pitch;
                p_dst = p_pic->p[0].p_pixels + i * p_pic->p[0].i_pitch;
                for ( j = 0; j < p_surface->w; j++ )
                {
                    SDL_GetRGBA( *(uint32_t*)p_src, p_surface->format,
                                &r, &g, &b, &a );
                    *(p_dst++) = b;
                    *(p_dst++) = g;
                    *(p_dst++) = r;
                    *(p_dst++) = a;
                    p_src += 4;
                }
            }
            break;
        }
    }

    p_pic->date = (p_block->i_pts > VLC_TS_INVALID) ?
        p_block->i_pts : p_block->i_dts;

    SDL_FreeSurface( p_surface );
    block_Release( p_block ); *pp_block = NULL;
    return p_pic;

error:
    if ( p_surface != NULL ) SDL_FreeSurface( p_surface );
    block_Release( p_block ); *pp_block = NULL;
    return NULL;
}
Exemple #12
0
/*****************************************************************************
 * Resample: convert a buffer
 *****************************************************************************/
static block_t *Resample( filter_t * p_filter, block_t * p_in_buf )
{
    if( !p_in_buf || !p_in_buf->i_nb_samples )
    {
        if( p_in_buf )
            block_Release( p_in_buf );
        return NULL;
    }

    filter_sys_t *p_sys = p_filter->p_sys;
    unsigned int i_out_rate = p_filter->fmt_out.audio.i_rate;
    int i_nb_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio );

    /* Check if we really need to run the resampler */
    if( i_out_rate == p_filter->fmt_in.audio.i_rate )
    {
        if( !(p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) &&
            p_sys->i_old_wing )
        {
            /* output the whole thing with the samples from last time */
            p_in_buf = block_Realloc( p_in_buf,
                p_sys->i_old_wing * p_filter->fmt_in.audio.i_bytes_per_frame,
                p_in_buf->i_buffer );
            if( !p_in_buf )
                return NULL;
            memcpy( p_in_buf->p_buffer, p_sys->p_buf +
                    i_nb_channels * p_sys->i_old_wing,
                    p_sys->i_old_wing *
                    p_filter->fmt_in.audio.i_bytes_per_frame );

            p_in_buf->i_nb_samples += p_sys->i_old_wing;

            p_in_buf->i_pts = date_Get( &p_sys->end_date );
            p_in_buf->i_length =
                date_Increment( &p_sys->end_date,
                                p_in_buf->i_nb_samples ) - p_in_buf->i_pts;
        }
        p_sys->i_old_wing = 0;
        p_sys->b_first = true;
        return p_in_buf;
    }

    unsigned i_bytes_per_frame = p_filter->fmt_out.audio.i_channels *
                                 p_filter->fmt_out.audio.i_bitspersample / 8;
    size_t i_out_size = i_bytes_per_frame * ( 1 + ( p_in_buf->i_nb_samples *
              p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate) )
            + p_filter->p_sys->i_buf_size;
    block_t *p_out_buf = filter_NewAudioBuffer( p_filter, i_out_size );
    if( !p_out_buf )
        return NULL;
    float *p_out = (float *)p_out_buf->p_buffer;

    if( (p_in_buf->i_flags & BLOCK_FLAG_DISCONTINUITY) || p_sys->b_first )
    {
        /* Continuity in sound samples has been broken, we'd better reset
         * everything. */
        p_out_buf->i_flags |= BLOCK_FLAG_DISCONTINUITY;
        p_sys->i_remainder = 0;
        date_Init( &p_sys->end_date, i_out_rate, 1 );
        date_Set( &p_sys->end_date, p_in_buf->i_pts );
        p_sys->d_old_factor = 1;
        p_sys->i_old_wing   = 0;
        p_sys->b_first = false;
    }

    int i_in_nb = p_in_buf->i_nb_samples;
    int i_in, i_out = 0;
    double d_factor, d_scale_factor, d_old_scale_factor;
    int i_filter_wing;

#if 0
    msg_Err( p_filter, "old rate: %i, old factor: %f, old wing: %i, i_in: %i",
             p_sys->i_old_rate, p_sys->d_old_factor,
             p_sys->i_old_wing, i_in_nb );
#endif

    /* Prepare the source buffer */
    i_in_nb += (p_sys->i_old_wing * 2);

    float p_in_orig[i_in_nb * p_filter->fmt_in.audio.i_bytes_per_frame / 4],
         *p_in = p_in_orig;

    /* Copy all our samples in p_in */
    if( p_sys->i_old_wing )
    {
        vlc_memcpy( p_in, p_sys->p_buf,
                    p_sys->i_old_wing * 2 *
                      p_filter->fmt_in.audio.i_bytes_per_frame );
    }
    /* XXX: why i_nb_channels instead of i_bytes_per_frame??? */
    vlc_memcpy( p_in + p_sys->i_old_wing * 2 * i_nb_channels,
                p_in_buf->p_buffer,
                p_in_buf->i_nb_samples * p_filter->fmt_in.audio.i_bytes_per_frame );
    block_Release( p_in_buf );

    /* Make sure the output buffer is reset */
    memset( p_out, 0, p_out_buf->i_buffer );

    /* Calculate the new length of the filter wing */
    d_factor = (double)i_out_rate / p_filter->fmt_in.audio.i_rate;
    i_filter_wing = ((SMALL_FILTER_NMULT+1)/2.0) * __MAX(1.0,1.0/d_factor) + 1;

    /* Account for increased filter gain when using factors less than 1 */
    d_old_scale_factor = SMALL_FILTER_SCALE *
        p_sys->d_old_factor + 0.5;
    d_scale_factor = SMALL_FILTER_SCALE * d_factor + 0.5;

    /* Apply the old rate until we have enough samples for the new one */
    i_in = p_sys->i_old_wing;
    p_in += p_sys->i_old_wing * i_nb_channels;
    for( ; i_in < i_filter_wing &&
           (i_in + p_sys->i_old_wing) < i_in_nb; i_in++ )
    {
        if( p_sys->d_old_factor == 1 )
        {
            /* Just copy the samples */
            memcpy( p_out, p_in,
                    p_filter->fmt_in.audio.i_bytes_per_frame );
            p_in += i_nb_channels;
            p_out += i_nb_channels;
            i_out++;
            continue;
        }

        while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate )
        {

            if( p_sys->d_old_factor >= 1 )
            {
                /* FilterFloatUP() is faster if we can use it */

                /* Perform left-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->fmt_out.audio.i_rate -
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate,
                               1, i_nb_channels );

#if 0
                /* Normalize for unity filter gain */
                for( i = 0; i < i_nb_channels; i++ )
                {
                    *(p_out+i) *= d_old_scale_factor;
                }
#endif

                /* Sanity check */
                if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame
                    <= (unsigned int)i_out+1 )
                {
                    p_out += i_nb_channels;
                    i_out++;
                    p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
                    break;
                }
            }
            else
            {
                /* Perform left-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->fmt_out.audio.i_rate -
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
                               1, i_nb_channels );
            }

            p_out += i_nb_channels;
            i_out++;

            p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
        }

        p_in += i_nb_channels;
        p_sys->i_remainder -= p_filter->fmt_out.audio.i_rate;
    }

    /* Apply the new rate for the rest of the samples */
    if( i_in < i_in_nb - i_filter_wing )
    {
        p_sys->d_old_factor = d_factor;
        p_sys->i_old_wing   = i_filter_wing;
    }
    for( ; i_in < i_in_nb - i_filter_wing; i_in++ )
    {
        while( p_sys->i_remainder < p_filter->fmt_out.audio.i_rate )
        {

            if( d_factor >= 1 )
            {
                /* FilterFloatUP() is faster if we can use it */

                /* Perform left-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate,
                               -1, i_nb_channels );

                /* Perform right-wing inner product */
                FilterFloatUP( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->fmt_out.audio.i_rate -
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate,
                               1, i_nb_channels );

#if 0
                /* Normalize for unity filter gain */
                for( int i = 0; i < i_nb_channels; i++ )
                {
                    *(p_out+i) *= d_old_scale_factor;
                }
#endif
                /* Sanity check */
                if( p_out_buf->i_buffer/p_filter->fmt_in.audio.i_bytes_per_frame
                    <= (unsigned int)i_out+1 )
                {
                    p_out += i_nb_channels;
                    i_out++;
                    p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
                    break;
                }
            }
            else
            {
                /* Perform left-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in, p_out,
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
                               -1, i_nb_channels );
                /* Perform right-wing inner product */
                FilterFloatUD( SMALL_FILTER_FLOAT_IMP, SMALL_FILTER_FLOAT_IMPD,
                               SMALL_FILTER_NWING, p_in + i_nb_channels, p_out,
                               p_filter->fmt_out.audio.i_rate -
                               p_sys->i_remainder,
                               p_filter->fmt_out.audio.i_rate, p_filter->fmt_in.audio.i_rate,
                               1, i_nb_channels );
            }

            p_out += i_nb_channels;
            i_out++;

            p_sys->i_remainder += p_filter->fmt_in.audio.i_rate;
        }

        p_in += i_nb_channels;
        p_sys->i_remainder -= p_filter->fmt_out.audio.i_rate;
    }

    /* Finalize aout buffer */
    p_out_buf->i_nb_samples = i_out;
    p_out_buf->i_pts = date_Get( &p_sys->end_date );
    p_out_buf->i_length = date_Increment( &p_sys->end_date,
                                  p_out_buf->i_nb_samples ) - p_out_buf->i_pts;

    p_out_buf->i_buffer = p_out_buf->i_nb_samples *
        i_nb_channels * sizeof(int32_t);

    /* Buffer i_filter_wing * 2 samples for next time */
    if( p_sys->i_old_wing )
    {
        size_t newsize = p_sys->i_old_wing * 2
                         * p_filter->fmt_in.audio.i_bytes_per_frame;
        if( newsize > p_sys->i_buf_size )
        {
            free( p_sys->p_buf );
            p_sys->p_buf = malloc( newsize );
            if( p_sys->p_buf != NULL )
                p_sys->i_buf_size = newsize;
            else
            {
                p_sys->i_buf_size = p_sys->i_old_wing = 0; /* oops! */
                return p_out_buf;
            }
        }
        memcpy( p_sys->p_buf,
                p_in_orig + (i_in_nb - 2 * p_sys->i_old_wing) *
                i_nb_channels, (2 * p_sys->i_old_wing) *
                p_filter->fmt_in.audio.i_bytes_per_frame );
    }

#if 0
    msg_Err( p_filter, "p_out size: %i, nb bytes out: %i", p_out_buf->i_buffer,
             i_out * p_filter->fmt_in.audio.i_bytes_per_frame );
#endif

    return p_out_buf;
}
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 );
}
Exemple #14
0
static void FilterPlanar( vout_thread_t *p_vout,
                          const picture_t *p_pic, picture_t *p_outpic )
{
    int i_index;
    switch( p_vout->p_sys->i_mode )
    {
        case TRANSFORM_MODE_90:
            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
            {
                int i_pitch = p_pic->p[i_index].i_pitch;

                uint8_t *p_in = p_pic->p[i_index].p_pixels;

                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
                uint8_t *p_out_end = p_out +
                    p_outpic->p[i_index].i_visible_lines *
                    p_outpic->p[i_index].i_pitch;

                for( ; p_out < p_out_end ; )
                {
                    uint8_t *p_line_end;

                    p_out_end -= p_outpic->p[i_index].i_pitch
                                  - p_outpic->p[i_index].i_visible_pitch;
                    p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
                        i_pitch;

                    for( ; p_in < p_line_end ; )
                    {
                        p_line_end -= i_pitch;
                        *(--p_out_end) = *p_line_end;
                    }

                    p_in++;
                }
            }
            break;

        case TRANSFORM_MODE_180:
            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
            {
                uint8_t *p_in = p_pic->p[i_index].p_pixels;
                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
                                            * p_pic->p[i_index].i_pitch;

                uint8_t *p_out = p_outpic->p[i_index].p_pixels;

                for( ; p_in < p_in_end ; )
                {
                    uint8_t *p_line_start = p_in_end
                                             - p_pic->p[i_index].i_pitch;
                    p_in_end -= p_pic->p[i_index].i_pitch
                                 - p_pic->p[i_index].i_visible_pitch;

                    for( ; p_line_start < p_in_end ; )
                    {
                        *p_out++ = *(--p_in_end);
                    }

                    p_out += p_outpic->p[i_index].i_pitch
                              - p_outpic->p[i_index].i_visible_pitch;
                }
            }
            break;

        case TRANSFORM_MODE_270:
            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
            {
                int i_pitch = p_pic->p[i_index].i_pitch;

                uint8_t *p_in = p_pic->p[i_index].p_pixels;

                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
                uint8_t *p_out_end = p_out +
                    p_outpic->p[i_index].i_visible_lines *
                    p_outpic->p[i_index].i_pitch;

                for( ; p_out < p_out_end ; )
                {
                    uint8_t *p_in_end;

                    p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
                        i_pitch;

                    for( ; p_in < p_in_end ; )
                    {
                        p_in_end -= i_pitch;
                        *p_out++ = *p_in_end;
                    }

                    p_out += p_outpic->p[i_index].i_pitch
                              - p_outpic->p[i_index].i_visible_pitch;
                    p_in++;
                }
            }
            break;

        case TRANSFORM_MODE_VFLIP:
            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
            {
                uint8_t *p_in = p_pic->p[i_index].p_pixels;
                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
                                            * p_pic->p[i_index].i_pitch;

                uint8_t *p_out = p_outpic->p[i_index].p_pixels;

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

        case TRANSFORM_MODE_HFLIP:
            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
            {
                uint8_t *p_in = p_pic->p[i_index].p_pixels;
                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
                                         * p_pic->p[i_index].i_pitch;

                uint8_t *p_out = p_outpic->p[i_index].p_pixels;

                for( ; p_in < p_in_end ; )
                {
                    uint8_t *p_line_end = p_in
                                        + p_pic->p[i_index].i_visible_pitch;

                    for( ; p_in < p_line_end ; )
                    {
                        *p_out++ = *(--p_line_end);
                    }

                    p_in += p_pic->p[i_index].i_pitch;
                    p_out += p_outpic->p[i_index].i_pitch
                                - p_outpic->p[i_index].i_visible_pitch;
                }
            }
            break;

        default:
            break;
    }
}
Exemple #15
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 #16
0
/*****************************************************************************
 * DoWork: mix a new output buffer
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
    int i = 0;
    aout_input_t * p_input = p_aout->pp_inputs[i];
    int i_nb_channels = aout_FormatNbChannels( &p_aout->mixer.mixer );
    int i_nb_bytes = p_buffer->i_nb_samples * sizeof(int32_t)
                      * i_nb_channels;
    uint8_t * p_in;
    uint8_t * p_out;

    while ( p_input->b_error )
    {
        p_input = p_aout->pp_inputs[++i];
        /* This can't crash because if no input has b_error == 0, the
         * audio mixer cannot run and we can't be here. */
    }
    p_in = p_input->p_first_byte_to_mix;
    p_out = p_buffer->p_buffer;

    for ( ; ; )
    {
        ptrdiff_t i_available_bytes = (p_input->fifo.p_first->p_buffer
                                        - p_in)
                                        + p_input->fifo.p_first->i_nb_samples
                                           * sizeof(int32_t)
                                           * i_nb_channels;

        if ( i_available_bytes < i_nb_bytes )
        {
            aout_buffer_t * p_old_buffer;

            vlc_memcpy( p_out, p_in, i_available_bytes );
            i_nb_bytes -= i_available_bytes;
            p_out += i_available_bytes;

            /* Next buffer */
            p_old_buffer = aout_FifoPop( p_aout, &p_input->fifo );
            aout_BufferFree( p_old_buffer );
            if ( p_input->fifo.p_first == NULL )
            {
                msg_Err( p_aout, "internal amix error" );
                return;
            }
            p_in = p_input->fifo.p_first->p_buffer;
        }
        else
        {
            vlc_memcpy( p_out, p_in, i_nb_bytes );
            p_input->p_first_byte_to_mix = p_in + i_nb_bytes;
            break;
        }
    }

    /* Empty other FIFOs to avoid a memory leak. */
    for ( i++; i < p_aout->i_nb_inputs; i++ )
    {
        aout_fifo_t * p_fifo;
        aout_buffer_t * p_deleted;

        p_input = p_aout->pp_inputs[i];
        if ( p_input->b_error ) continue;
        p_fifo = &p_input->fifo;
        p_deleted = p_fifo->p_first;
        while ( p_deleted != NULL )
        {
            aout_buffer_t * p_next = p_deleted->p_next;
            aout_BufferFree( p_deleted );
            p_deleted = p_next;
        }
        p_fifo->p_first = NULL;
        p_fifo->pp_last = &p_fifo->p_first;
    }
}
Exemple #17
0
/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out encapsulation units.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block, *p_output_chain = NULL;
    int i_plane, i_line, i_width, i_src_stride;
    uint8_t *p_dst;

    /* we only know if the sequence is interlaced when the first
     * picture arrives, so final setup is done here */
    /* XXX todo, detect change of interlace */
    p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first;
    p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive;

    if( p_sys->b_auto_field_coding )
        p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive;

    if( !p_sys->p_dirac )
    {
        date_t date;
        /* Initialise the encoder with the encoder context */
        p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 );
        if( !p_sys->p_dirac )
        {
            msg_Err( p_enc, "Failed to initialize dirac encoder" );
            return NULL;
        }
        date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
#if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
        int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac );
        i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1;
        date_Increment( &date, i_delayinpics );
#else
        date_Increment( &date, 1 );
#endif
        p_sys->i_pts_offset = date_Get( &date );

        /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
         * for each frame input. Calculate time between fields for offsetting
         * the second field later. */
        if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
        {
            date_Set( &date, 0 );
            date_Increment( &date, 1 );
            p_sys->i_field_time = date_Get( &date ) / 2;
        }
    }

    /* Copy input picture into encoder input buffer (stride by stride) */
    /* Would be lovely to just pass the picture in, but there is noway for the
     * library to free it */
    p_dst = p_sys->p_buffer_in;
    for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
    {
        uint8_t *p_src = p_pic->p[i_plane].p_pixels;
        i_width = p_pic->p[i_plane].i_visible_pitch;
        i_src_stride = p_pic->p[i_plane].i_pitch;

        for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
        {
            vlc_memcpy( p_dst, p_src, i_width );
            p_dst += i_width;
            p_src += i_src_stride;
        }
    }

    /* Load one frame of data into encoder */
    if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
                            p_sys->i_buffer_in ) < 0 )
    {
        msg_Dbg( p_enc, "dirac_encoder_load() error" );
        return NULL;
    }

    /* store pts in a lookaside buffer, so that the same pts may
     * be used for the picture in coded order */
    StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
    p_sys->i_input_picnum++;

    /* store dts in a queue, so that they appear in order in
     * coded order */
    p_block = block_New( p_enc, 1 );
    if( !p_block )
        return NULL;
    p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
    block_FifoPut( p_sys->p_dts_fifo, p_block );
    p_block = NULL;

    /* for field coding mode, insert an extra value into both the
     * pts lookaside buffer and dts queue, offset to correspond
     * to a one field delay. */
    if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
    {
        StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
        p_sys->i_input_picnum++;

        p_block = block_New( p_enc, 1 );
        if( !p_block )
            return NULL;
        p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
        block_FifoPut( p_sys->p_dts_fifo, p_block );
        p_block = NULL;
    }

    dirac_encoder_state_t state;
    /* Retrieve encoded frames from encoder */
    do
    {
        p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
        p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out;
        state = dirac_encoder_output( p_sys->p_dirac );
        switch( state )
        {
        case ENC_STATE_AVAIL: {
            uint32_t pic_num;

            /* extract data from encoder temporary buffer. */
            p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
            if( !p_block )
                return NULL;
            memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
                    p_sys->p_dirac->enc_buf.size );

            /* if some flags were set for a previous block, prevent
             * them from getting lost */
            if( p_sys->p_chain )
                p_block->i_flags |= p_sys->p_chain->i_flags;

            /* store all extracted blocks in a chain and gather up when an
             * entire encapsulation unit is avaliable (ends with a picture) */
            block_ChainAppend( &p_sys->p_chain, p_block );

            /* Presence of a Sequence header indicates a seek point */
            if( 0 == p_block->p_buffer[4] )
            {
                p_block->i_flags |= BLOCK_FLAG_TYPE_I;

                if( !p_enc->fmt_out.p_extra ) {
                    const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
                    uint32_t len = GetDWBE( p_block->p_buffer + 5 );
                    /* if it hasn't been done so far, stash a copy of the
                     * sequence header for muxers such as ogg */
                    /* The OggDirac spec advises that a Dirac EOS DataUnit
                     * is appended to the sequence header to allow guard
                     * against poor streaming servers */
                    /* XXX, should this be done using the packetizer ? */
                    p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) );
                    if( !p_enc->fmt_out.p_extra )
                        return NULL;
                    memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len);
                    memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) );
                    SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
                    p_enc->fmt_out.i_extra = len + sizeof(eos);
                }
            }

            if( ReadDiracPictureNumber( &pic_num, p_block ) )
            {
                /* Finding a picture terminates an ecapsulation unit, gather
                 * all data and output; use the next dts value queued up
                 * and find correct pts in the tlb */
                p_block = block_FifoGet( p_sys->p_dts_fifo );
                p_sys->p_chain->i_dts = p_block->i_dts;
                p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num );
                block_Release( p_block );
                block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) );
                p_sys->p_chain = NULL;
            } else {
                p_block = NULL;
            }
            break;
            }

        case ENC_STATE_BUFFER:
            break;
        case ENC_STATE_INVALID:
        default:
            break;
        }
    } while( state == ENC_STATE_AVAIL );

    return p_output_chain;
}
/*****************************************************************************
 * Command functions
 *****************************************************************************/
static int exec_DataSharedMem( filter_t *p_filter,
                               const commandparams_t *p_params,
                               commandparams_t *p_results )
{
#if defined(HAVE_SYS_SHM_H)
    filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys;
    struct shmid_ds shminfo;
    overlay_t *p_ovl;
    size_t i_size;

    VLC_UNUSED(p_results);

    p_ovl = ListGet( &p_sys->overlays, p_params->i_id );
    if( p_ovl == NULL )
    {
        msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id );
        return VLC_EGENERIC;
    }

    if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 )
    {
        msg_Err( p_filter, "Unable to access shared memory" );
        return VLC_EGENERIC;
    }
    i_size = shminfo.shm_segsz;

    if( p_params->fourcc == VLC_CODEC_TEXT )
    {
        char *p_data;

        if( (p_params->i_height != 1) || (p_params->i_width < 1) )
        {
            msg_Err( p_filter,
                     "Invalid width and/or height. when specifying text height "
                     "must be 1 and width the number of bytes in the string, "
                     "including the null terminator" );
            return VLC_EGENERIC;
        }

        if( (size_t)p_params->i_width > i_size )
        {
            msg_Err( p_filter,
                     "Insufficient data in shared memory. need %d, got %zu",
                     p_params->i_width, i_size );
            return VLC_EGENERIC;
        }

        p_ovl->data.p_text = malloc( p_params->i_width );
        if( p_ovl->data.p_text == NULL )
        {
            msg_Err( p_filter, "Unable to allocate string storage" );
            return VLC_ENOMEM;
        }

        video_format_Setup( &p_ovl->format, VLC_CODEC_TEXT,
                            0, 0, 0, 1 );

        p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
        if( p_data == NULL )
        {
            msg_Err( p_filter, "Unable to attach to shared memory" );
            free( p_ovl->data.p_text );
            p_ovl->data.p_text = NULL;
            return VLC_ENOMEM;
        }
        memcpy( p_ovl->data.p_text, p_data, p_params->i_width );

        shmdt( p_data );
    }
    else
    {
        uint8_t *p_data, *p_in;
        size_t i_neededsize = 0;

        p_ovl->data.p_pic = picture_New( p_params->fourcc,
                                         p_params->i_width, p_params->i_height,
                                         1, 1 );
        if( p_ovl->data.p_pic == NULL )
            return VLC_ENOMEM;

        p_ovl->format = p_ovl->data.p_pic->format;

        for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
             ++i_plane )
        {
            i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines *
                            p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
        }

        if( i_neededsize > i_size )
        {
            msg_Err( p_filter,
                     "Insufficient data in shared memory. need %zu, got %zu",
                     i_neededsize, i_size );
            picture_Release( p_ovl->data.p_pic );
            p_ovl->data.p_pic = NULL;
            return VLC_EGENERIC;
        }

        p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY );
        if( p_data == NULL )
        {
            msg_Err( p_filter, "Unable to attach to shared memory" );
            picture_Release( p_ovl->data.p_pic );
            p_ovl->data.p_pic = NULL;
            return VLC_ENOMEM;
        }

        p_in = p_data;
        for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes;
             ++i_plane )
        {
            uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels;
            for( size_t i_line = 0;
                 i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines;
                 ++i_line )
            {
                vlc_memcpy( p_out, p_in,
                            p_ovl->data.p_pic->p[i_plane].i_visible_pitch );
                p_out += p_ovl->data.p_pic->p[i_plane].i_pitch;
                p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch;
            }
        }
        shmdt( p_data );
    }
    p_sys->b_updated = p_ovl->b_active;

    return VLC_SUCCESS;
#else
    VLC_UNUSED(p_params);
    VLC_UNUSED(p_results);

    msg_Err( p_filter, "system doesn't support shared memory" );
    return VLC_EGENERIC;
#endif
}
/*****************************************************************************
 * Render: displays previously rendered output
 *****************************************************************************
 * This function send the currently rendered image to Invert 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;
    int i_planes;

    if( !p_pic ) return NULL;

    p_outpic = filter_NewPicture( p_filter );
    if( !p_outpic )
    {
        msg_Warn( p_filter, "can't get output picture" );
        picture_Release( p_pic );
        return NULL;
    }

    if( p_pic->format.i_chroma == VLC_CODEC_YUVA )
    {
        /* We don't want to invert the alpha plane */
        i_planes = p_pic->i_planes - 1;
        vlc_memcpy(
            p_outpic->p[A_PLANE].p_pixels, p_pic->p[A_PLANE].p_pixels,
            p_pic->p[A_PLANE].i_pitch *  p_pic->p[A_PLANE].i_lines );
    }
    else
    {
        i_planes = p_pic->i_planes;
    }

    for( i_index = 0 ; i_index < i_planes ; i_index++ )
    {
        uint8_t *p_in, *p_in_end, *p_line_end, *p_out;

        p_in = p_pic->p[i_index].p_pixels;
        p_in_end = p_in + p_pic->p[i_index].i_visible_lines
                           * p_pic->p[i_index].i_pitch;

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

        for( ; p_in < p_in_end ; )
        {
            uint64_t *p_in64, *p_out64;

            p_line_end = p_in + p_pic->p[i_index].i_visible_pitch - 64;

            p_in64 = (uint64_t*)p_in;
            p_out64 = (uint64_t*)p_out;

            while( p_in64 < (uint64_t *)p_line_end )
            {
                /* Do 64 pixels at a time */
                *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
                *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
                *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
                *p_out64++ = ~*p_in64++; *p_out64++ = ~*p_in64++;
            }

            p_in = (uint8_t*)p_in64;
            p_out = (uint8_t*)p_out64;
            p_line_end += 64;

            for( ; p_in < p_line_end ; )
            {
                *p_out++ = ~( *p_in++ );
            }

            p_in += p_pic->p[i_index].i_pitch
                     - p_pic->p[i_index].i_visible_pitch;
            p_out += p_outpic->p[i_index].i_pitch
                     - p_outpic->p[i_index].i_visible_pitch;
        }
    }

    return CopyInfoAndRelease( p_outpic, p_pic );
}
Exemple #20
0
/*****************************************************************************
 * DoWork: convert a buffer
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    int32_t *p_in, *p_out = (int32_t*)p_out_buf->p_buffer;
#ifndef HAVE_ALLOCA
    int32_t *p_in_orig;
#endif

    unsigned int i_nb_channels = aout_FormatNbChannels( &p_filter->input );
    unsigned int i_in_nb = p_in_buf->i_nb_samples;
    unsigned int i_out_nb = i_in_nb * p_filter->output.i_rate
                                    / p_filter->input.i_rate;
    unsigned int i_sample_bytes = i_nb_channels * sizeof(int32_t);
    unsigned int i_out, i_chan, i_remainder = 0;

    /* Check if we really need to run the resampler */
    if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate )
    {
        return;
    }

#ifdef HAVE_ALLOCA
    p_in = (int32_t *)alloca( p_in_buf->i_nb_bytes );
#else
    p_in_orig = p_in = (int32_t *)malloc( p_in_buf->i_nb_bytes );
#endif
    if( p_in == NULL )
    {
        return;
    }

    vlc_memcpy( p_in, p_in_buf->p_buffer, p_in_buf->i_nb_bytes );

    for( i_out = i_out_nb ; i_out-- ; )
    {
        for( i_chan = i_nb_channels ; i_chan ; )
        {
            i_chan--;
            p_out[i_chan] = p_in[i_chan];
        }
        p_out += i_nb_channels;

        i_remainder += p_filter->input.i_rate;
        while( i_remainder >= p_filter->output.i_rate )
        {
            p_in += i_nb_channels;
            i_remainder -= p_filter->output.i_rate;
        }
    }

    p_out_buf->i_nb_samples = i_out_nb;
    p_out_buf->i_nb_bytes = i_out_nb * i_sample_bytes;
    p_out_buf->start_date = p_in_buf->start_date;
    p_out_buf->end_date = p_out_buf->start_date + p_out_buf->i_nb_samples *
        1000000 / p_filter->output.i_rate;

#ifndef HAVE_ALLOCA
    free( p_in_orig );
#endif

}