コード例 #1
0
static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt,
                                 bool b_text,
                                 int i_columns, int i_rows, int i_align,
                                 mtime_t i_pts )
{
    video_format_t fmt;
    subpicture_t *p_spu;

    /* If there is a page or sub to render, then we do that here */
    /* Create the subpicture unit */
    p_spu = decoder_NewSubpicture( p_dec, NULL );
    if( !p_spu )
    {
        msg_Warn( p_dec, "can't get spu buffer" );
        return NULL;
    }

    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = b_text ? VLC_CODEC_TEXT : VLC_CODEC_RGBA;
    fmt.i_sar_num = 0;
    fmt.i_sar_den = 1;
    if( b_text )
    {
        fmt.i_bits_per_pixel = 0;
    }
    else
    {
        fmt.i_width = fmt.i_visible_width = i_columns * 12;
        fmt.i_height = fmt.i_visible_height = i_rows * 10;
        fmt.i_bits_per_pixel = 32;
    }
    fmt.i_x_offset = fmt.i_y_offset = 0;

    p_spu->p_region = subpicture_region_New( &fmt );
    if( p_spu->p_region == NULL )
    {
        msg_Err( p_dec, "cannot allocate SPU region" );
        decoder_DeleteSubpicture( p_dec, p_spu );
        return NULL;
    }

    p_spu->p_region->i_x = 0;
    p_spu->p_region->i_y = 0;
    p_spu->p_region->i_align = i_align;

    p_spu->i_start = i_pts;
    p_spu->i_stop = 0;
    p_spu->b_ephemer = true;
    p_spu->b_absolute = true;

    if( !b_text )
    {
        p_spu->i_original_picture_width = fmt.i_width;
        p_spu->i_original_picture_height = fmt.i_height;
    }

    /* */
    *p_fmt = fmt;
    return p_spu;
}
コード例 #2
0
/*****************************************************************************
 * Decode:
 *****************************************************************************/
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    block_t         *p_block;
    subpicture_t    *p_spu = NULL;
    video_format_t  fmt;
    bool            b_cached = false;
    vbi_page        p_page;
    const uint8_t   *p_pos;
    unsigned int    i_left;

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

    p_block = *pp_block;
    *pp_block = NULL;

    p_pos = p_block->p_buffer;
    i_left = p_block->i_buffer;

    while( i_left > 0 )
    {
        vbi_sliced      p_sliced[MAX_SLICES];
        unsigned int    i_lines = 0;
        int64_t         i_pts;

        i_lines = vbi_dvb_demux_cor( p_sys->p_dvb_demux, p_sliced,
                                     MAX_SLICES, &i_pts, &p_pos, &i_left );

        if( i_lines > 0 )
            vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, i_pts / 90000.0 );
    }

    /* */
    vlc_mutex_lock( &p_sys->lock );
    const int i_align = p_sys->i_align;
    const unsigned int i_wanted_page = p_sys->i_wanted_page;
    const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage;
    const bool b_opaque = p_sys->b_opaque;
    vlc_mutex_unlock( &p_sys->lock );

    /* Try to see if the page we want is in the cache yet */
    memset( &p_page, 0, sizeof(vbi_page) );
    b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page,
                                  vbi_dec2bcd( i_wanted_page ),
                                  i_wanted_subpage, VBI_WST_LEVEL_3p5,
                                  25, true );

    if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update )
        goto error;

    if( !b_cached )
    {
        if( p_sys->i_last_page != i_wanted_page )
        {
            /* We need to reset the subtitle */
            p_spu = Subpicture( p_dec, &fmt, true,
                                p_page.columns, p_page.rows,
                                i_align, p_block->i_pts );
            if( !p_spu )
                goto error;
            p_spu->p_region->psz_text = strdup("");

            p_sys->b_update = true;
            p_sys->i_last_page = i_wanted_page;
            goto exit;
        }
        goto error;
    }

    p_sys->b_update = false;
    p_sys->i_last_page = i_wanted_page;
#ifdef ZVBI_DEBUG
    msg_Dbg( p_dec, "we now have page: %d ready for display",
             i_wanted_page );
#endif
    /* If there is a page or sub to render, then we do that here */
    /* Create the subpicture unit */
    p_spu = Subpicture( p_dec, &fmt, p_sys->b_text,
                        p_page.columns, p_page.rows,
                        i_align, p_block->i_pts );
    if( !p_spu )
        goto error;

    if( p_sys->b_text )
    {
        unsigned int i_textsize = 7000;
        int i_total;
        char p_text[i_textsize+1];

        i_total = vbi_print_page_region( &p_page, p_text, i_textsize,
                        "UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows );
        p_text[i_total] = '\0';
        /* Strip off the pagenumber */
        if( i_total <= 40 )
            goto error;
        p_spu->p_region->psz_text = strdup( &p_text[8] );

#ifdef ZVBI_DEBUG
        msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text );
#endif
    }
    else
    {
        picture_t *p_pic = p_spu->p_region->p_picture;

        /* ZVBI is stupid enough to assume pitch == width */
        p_pic->p->i_pitch = 4 * fmt.i_width;
        vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32,
                          p_spu->p_region->p_picture->p->p_pixels, 1, 1 );

        vlc_mutex_lock( &p_sys->lock );
        memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ;
        vlc_mutex_unlock( &p_sys->lock );

        OpaquePage( p_pic, p_page, fmt, b_opaque );
    }

exit:
    vbi_unref_page( &p_page );
    block_Release( p_block );
    return p_spu;

error:
    vbi_unref_page( &p_page );
    if( p_spu != NULL )
    {
        decoder_DeleteSubpicture( p_dec, p_spu );
        p_spu = NULL;
    }

    block_Release( p_block );
    return NULL;
}
コード例 #3
0
ファイル: zvbi.c プロジェクト: sunqueen/vlc-2.2.4.32-2013
/*****************************************************************************
 * Decode:
 *****************************************************************************/
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    block_t         *p_block;
    subpicture_t    *p_spu = NULL;
    video_format_t  fmt;
    bool            b_cached = false;
    vbi_page        p_page;

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

    p_block = *pp_block;
    *pp_block = NULL;

    if( p_block->i_buffer > 0 &&
        ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) ||
          ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) )
    {
        vbi_sliced   *p_sliced = p_sys->p_vbi_sliced;
        unsigned int i_lines = 0;

        p_block->i_buffer--;
        p_block->p_buffer++;
        while( p_block->i_buffer >= 2 )
        {
            int      i_id   = p_block->p_buffer[0];
            unsigned i_size = p_block->p_buffer[1];

            if( 2 + i_size > p_block->i_buffer )
                break;

            if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES )
            {
                if(p_block->p_buffer[3] == 0xE4 )    /* framing_code */
                {
                    unsigned line_offset  = p_block->p_buffer[2] & 0x1f;
                    unsigned field_parity = p_block->p_buffer[2] & 0x20;

                    p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B;
                    if( line_offset > 0 )
                        p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313);
                    else
                        p_sliced[i_lines].line = 0;
                    for( int i = 0; i < 42; i++ )
                        p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] );
                    i_lines++;
                }
            }

            p_block->i_buffer -= 2 + i_size;
            p_block->p_buffer += 2 + i_size;
        }

        if( i_lines > 0 )
            vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, 0 );
    }

    /* */
    vlc_mutex_lock( &p_sys->lock );
    const int i_align = p_sys->i_align;
    const unsigned int i_wanted_page = p_sys->i_wanted_page;
    const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage;
    const bool b_opaque = p_sys->b_opaque;
    vlc_mutex_unlock( &p_sys->lock );

    /* Try to see if the page we want is in the cache yet */
    memset( &p_page, 0, sizeof(vbi_page) );
    b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page,
                                  vbi_dec2bcd( i_wanted_page ),
                                  i_wanted_subpage, VBI_WST_LEVEL_3p5,
                                  25, true );

    if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update )
        goto error;

    if( !b_cached )
    {
        if( p_sys->b_text && p_sys->i_last_page != i_wanted_page )
        {
            /* We need to reset the subtitle */
            p_spu = Subpicture( p_dec, &fmt, true,
                                p_page.columns, p_page.rows,
                                i_align, p_block->i_pts );
            if( !p_spu )
                goto error;
            subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
            p_spu_sys->text = strdup("");

            p_sys->b_update = true;
            p_sys->i_last_page = i_wanted_page;
            goto exit;
        }
        goto error;
    }

    p_sys->b_update = false;
    p_sys->i_last_page = i_wanted_page;
#ifdef ZVBI_DEBUG
    msg_Dbg( p_dec, "we now have page: %d ready for display",
             i_wanted_page );
#endif

    /* Ignore transparent rows at the beginning and end */
    int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns );
    int i_num_rows;
    if ( i_first_row < 0 ) {
        i_first_row = p_page.rows - 1;
        i_num_rows = 0;
    } else {
        i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1;
    }
#ifdef ZVBI_DEBUG
    msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i",
             i_first_row + 1, i_first_row + i_num_rows, p_page.rows );
#endif

    /* If there is a page or sub to render, then we do that here */
    /* Create the subpicture unit */
    p_spu = Subpicture( p_dec, &fmt, p_sys->b_text,
                        p_page.columns, i_num_rows,
                        i_align, p_block->i_pts );
    if( !p_spu )
        goto error;

    if( p_sys->b_text )
    {
        unsigned int i_textsize = 7000;
        int i_total,offset;
//        char p_text[i_textsize+1];
        char *p_text = (char *)malloc(i_textsize+1);			// sunqueen modify

        i_total = vbi_print_page_region( &p_page, p_text, i_textsize,
                        "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows );

        for( offset=1; offset<i_total && isspace( p_text[i_total-offset ] ); offset++)
           p_text[i_total-offset] = '\0';

        i_total -= offset;

        offset=0;
        while( offset < i_total && isspace( p_text[offset] ) )
           offset++;

        subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
        p_spu_sys->text = strdup( &p_text[offset] );

        p_spu_sys->align = i_align;
        p_spu_sys->i_font_height_percent = 5;
        p_spu_sys->renderbg = b_opaque;

#ifdef ZVBI_DEBUG
        msg_Info( p_dec, "page %x-%x(%d)\n\"%s\"", p_page.pgno, p_page.subno, i_total, &p_text[offset] );
#endif
		free(p_text);			// sunqueen add
    }
    else
    {
        picture_t *p_pic = p_spu->p_region->p_picture;

        /* ZVBI is stupid enough to assume pitch == width */
        p_pic->p->i_pitch = 4 * fmt.i_width;

        /* Maintain subtitle postion */
        p_spu->p_region->i_y = i_first_row*10;
        p_spu->i_original_picture_width = p_page.columns*12;
        p_spu->i_original_picture_height = p_page.rows*10;

        vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32,
                          p_spu->p_region->p_picture->p->p_pixels, -1,
                          0, i_first_row, p_page.columns, i_num_rows,
                          1, 1);

        vlc_mutex_lock( &p_sys->lock );
        memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ;
        vlc_mutex_unlock( &p_sys->lock );

        OpaquePage( p_pic, &p_page, fmt, b_opaque, i_first_row * p_page.columns );
    }

exit:
    vbi_unref_page( &p_page );
    block_Release( p_block );
    return p_spu;

error:
    vbi_unref_page( &p_page );
    if( p_spu != NULL )
    {
        decoder_DeleteSubpicture( p_dec, p_spu );
        p_spu = NULL;
    }

    block_Release( p_block );
    return NULL;
}
コード例 #4
0
ファイル: libass.c プロジェクト: 371816210/vlc_vlc
/****************************************************************************
 * DecodeBlock:
 ****************************************************************************/
static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    subpicture_t *p_spu = NULL;
    block_t *p_block;

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

    p_block = *pp_block;
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        p_sys->i_max_stop = VLC_TS_INVALID;
        block_Release( p_block );
        return NULL;
    }
    *pp_block = NULL;

    if( p_block->i_buffer == 0 || p_block->p_buffer[0] == '\0' )
    {
        block_Release( p_block );
        return NULL;
    }

    subpicture_updater_sys_t *p_spu_sys = malloc( sizeof(*p_spu_sys) );
    if( !p_spu_sys )
    {
        block_Release( p_block );
        return NULL;
    }

    subpicture_updater_t updater = {
        .pf_validate = SubpictureValidate,
        .pf_update   = SubpictureUpdate,
        .pf_destroy  = SubpictureDestroy,
        .p_sys       = p_spu_sys,
    };
    p_spu = decoder_NewSubpicture( p_dec, &updater );
    if( !p_spu )
    {
        msg_Warn( p_dec, "can't get spu buffer" );
        free( p_spu_sys );
        block_Release( p_block );
        return NULL;
    }

    p_spu_sys->p_img = NULL;
    p_spu_sys->p_dec_sys = p_sys;
    p_spu_sys->i_subs_len = p_block->i_buffer;
    p_spu_sys->p_subs_data = malloc( p_block->i_buffer );
    p_spu_sys->i_pts = p_block->i_pts;
    if( !p_spu_sys->p_subs_data )
    {
        decoder_DeleteSubpicture( p_dec, p_spu );
        block_Release( p_block );
        return NULL;
    }
    memcpy( p_spu_sys->p_subs_data, p_block->p_buffer,
            p_block->i_buffer );

    p_spu->i_start = p_block->i_pts;
    p_spu->i_stop = __MAX( p_sys->i_max_stop, p_block->i_pts + p_block->i_length );
    p_spu->b_ephemer = true;
    p_spu->b_absolute = true;

    p_sys->i_max_stop = p_spu->i_stop;

    vlc_mutex_lock( &p_sys->lock );
    if( p_sys->p_track )
    {
        ass_process_chunk( p_sys->p_track, p_spu_sys->p_subs_data, p_spu_sys->i_subs_len,
                           p_block->i_pts / 1000, p_block->i_length / 1000 );
    }
    vlc_mutex_unlock( &p_sys->lock );

    DecSysHold( p_sys ); /* Keep a reference for the returned subpicture */

    block_Release( p_block );

    return p_spu;
}
コード例 #5
0
ファイル: svcdsub.c プロジェクト: hustcalm/vlc-player
/*****************************************************************************
 * DecodePacket: parse and decode an subtitle packet
 *****************************************************************************
 * This function parses and decodes an SPU packet and, if valid, returns a
 * subpicture.
 *****************************************************************************/
static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    subpicture_t  *p_spu;
    subpicture_region_t *p_region;
    video_format_t fmt;
    video_palette_t palette;
    int i;

    /* Allocate the subpicture internal data. */
    p_spu = decoder_NewSubpicture( p_dec, NULL );
    if( !p_spu ) return NULL;

    p_spu->i_start = p_data->i_pts;
    p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
    p_spu->b_ephemer = true;

    /* Create new subtitle region */
    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_YUVP;

    /**
       The video on which the subtitle sits, is scaled, probably
       4:3. However subtitle bitmaps assume an 1:1 aspect ratio.

       FIXME: We should get the video aspect ratio from somewhere.
       Two candidates are the video and the other possibility would be
       the access module.
    */
    fmt.i_sar_num = p_sys->i_height;
    fmt.i_sar_den = p_sys->i_width;

    fmt.i_width = fmt.i_visible_width = p_sys->i_width;
    fmt.i_height = fmt.i_visible_height = p_sys->i_height;
    fmt.i_x_offset = fmt.i_y_offset = 0;
    fmt.p_palette = &palette;
    fmt.p_palette->i_entries = 4;
    for( i = 0; i < fmt.p_palette->i_entries; i++ )
    {
        fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
        fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
        fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
        fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
    }

    p_region = subpicture_region_New( &fmt );
    if( !p_region )
    {
        msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
        decoder_DeleteSubpicture( p_dec, p_spu );
        return NULL;
    }

    p_spu->p_region = p_region;
    p_region->i_x = p_sys->i_x_start;
    p_region->i_y = p_sys->i_y_start;

    SVCDSubRenderImage( p_dec, p_data, p_region );

    return p_spu;
}
コード例 #6
0
ファイル: zvbi.c プロジェクト: Flameeyes/vlc
/*****************************************************************************
 * Decode:
 *****************************************************************************/
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t   *p_sys = p_dec->p_sys;
    block_t         *p_block;
    subpicture_t    *p_spu = NULL;
    video_format_t  fmt;
    bool            b_cached = false;
    vbi_page        p_page;

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

    p_block = *pp_block;
    *pp_block = NULL;

    if( p_block->i_buffer > 0 &&
        ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) ||
          ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) )
    {
        vbi_sliced   *p_sliced = p_sys->p_vbi_sliced;
        unsigned int i_lines = 0;

        p_block->i_buffer--;
        p_block->p_buffer++;
        while( p_block->i_buffer >= 2 )
        {
            int      i_id   = p_block->p_buffer[0];
            unsigned i_size = p_block->p_buffer[1];

            if( 2 + i_size > p_block->i_buffer )
                break;

            if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES )
            {
                unsigned line_offset  = p_block->p_buffer[2] & 0x1f;
                unsigned field_parity = p_block->p_buffer[2] & 0x20;

                p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B;
                if( line_offset > 0 )
                    p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313);
                else
                    p_sliced[i_lines].line = 0;
                for( int i = 0; i < 42; i++ )
                    p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] );
                i_lines++;
            }

            p_block->i_buffer -= 2 + i_size;
            p_block->p_buffer += 2 + i_size;
        }

        if( i_lines > 0 )
            vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, (double)p_block->i_pts / 1000000 );
    }

    /* */
    vlc_mutex_lock( &p_sys->lock );
    const int i_align = p_sys->i_align;
    const unsigned int i_wanted_page = p_sys->i_wanted_page;
    const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage;
    const bool b_opaque = p_sys->b_opaque;
    vlc_mutex_unlock( &p_sys->lock );

    /* Try to see if the page we want is in the cache yet */
    memset( &p_page, 0, sizeof(vbi_page) );
    b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page,
                                  vbi_dec2bcd( i_wanted_page ),
                                  i_wanted_subpage, VBI_WST_LEVEL_3p5,
                                  25, true );

    if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update )
        goto error;

    if( !b_cached )
    {
        if( p_sys->i_last_page != i_wanted_page )
        {
            /* We need to reset the subtitle */
            p_spu = Subpicture( p_dec, &fmt, true,
                                p_page.columns, p_page.rows,
                                i_align, p_block->i_pts );
            if( !p_spu )
                goto error;
            p_spu->p_region->psz_text = strdup("");

            p_sys->b_update = true;
            p_sys->i_last_page = i_wanted_page;
            goto exit;
        }
        goto error;
    }

    p_sys->b_update = false;
    p_sys->i_last_page = i_wanted_page;
#ifdef ZVBI_DEBUG
    msg_Dbg( p_dec, "we now have page: %d ready for display",
             i_wanted_page );
#endif
    /* If there is a page or sub to render, then we do that here */
    /* Create the subpicture unit */
    p_spu = Subpicture( p_dec, &fmt, p_sys->b_text,
                        p_page.columns, p_page.rows,
                        i_align, p_block->i_pts );
    if( !p_spu )
        goto error;

    if( p_sys->b_text )
    {
        unsigned int i_textsize = 7000;
        int i_total;
        char p_text[i_textsize+1];

        i_total = vbi_print_page_region( &p_page, p_text, i_textsize,
                        "UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows );
        p_text[i_total] = '\0';
        /* Strip off the pagenumber */
        if( i_total <= 40 )
            goto error;
        p_spu->p_region->psz_text = strdup( &p_text[8] );

#ifdef ZVBI_DEBUG
        msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text );
#endif
    }
    else
    {
        picture_t *p_pic = p_spu->p_region->p_picture;

        /* ZVBI is stupid enough to assume pitch == width */
        p_pic->p->i_pitch = 4 * fmt.i_width;
        vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32,
                          p_spu->p_region->p_picture->p->p_pixels, 1, 1 );

        vlc_mutex_lock( &p_sys->lock );
        memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ;
        vlc_mutex_unlock( &p_sys->lock );

        OpaquePage( p_pic, p_page, fmt, b_opaque );
    }

exit:
    vbi_unref_page( &p_page );
    block_Release( p_block );
    return p_spu;

error:
    vbi_unref_page( &p_page );
    if( p_spu != NULL )
    {
        decoder_DeleteSubpicture( p_dec, p_spu );
        p_spu = NULL;
    }

    block_Release( p_block );
    return NULL;
}
コード例 #7
0
ファイル: subsdec.c プロジェクト: cmassiot/vlc-broadcast
/*****************************************************************************
 * ParseText: parse an text subtitle packet and send it to the video output
 *****************************************************************************/
static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    subpicture_t *p_spu = NULL;
    char *psz_subtitle = NULL;
    video_format_t fmt;

    /* We cannot display a subpicture with no date */
    if( p_block->i_pts <= VLC_TS_INVALID )
    {
        msg_Warn( p_dec, "subtitle without a date" );
        return NULL;
    }

    /* Check validity of packet data */
    /* An "empty" line containing only \0 can be used to force
       and ephemer picture from the screen */
    if( p_block->i_buffer < 1 )
    {
        msg_Warn( p_dec, "no subtitle data" );
        return NULL;
    }

    /* Should be resiliant against bad subtitles */
    psz_subtitle = malloc( p_block->i_buffer + 1 );
    if( psz_subtitle == NULL )
        return NULL;
    memcpy( psz_subtitle, p_block->p_buffer, p_block->i_buffer );
    psz_subtitle[p_block->i_buffer] = '\0';

    if( p_sys->iconv_handle == (vlc_iconv_t)-1 )
    {
        if (EnsureUTF8( psz_subtitle ) == NULL)
        {
            msg_Err( p_dec, "failed to convert subtitle encoding.\n"
                     "Try manually setting a character-encoding "
                     "before you open the file." );
        }
    }
    else
    {

        if( p_sys->b_autodetect_utf8 )
        {
            if( IsUTF8( psz_subtitle ) == NULL )
            {
                msg_Dbg( p_dec, "invalid UTF-8 sequence: "
                         "disabling UTF-8 subtitles autodetection" );
                p_sys->b_autodetect_utf8 = false;
            }
        }

        if( !p_sys->b_autodetect_utf8 )
        {
            size_t inbytes_left = strlen( psz_subtitle );
            size_t outbytes_left = 6 * inbytes_left;
            char *psz_new_subtitle = xmalloc( outbytes_left + 1 );
            char *psz_convert_buffer_out = psz_new_subtitle;
            const char *psz_convert_buffer_in = psz_subtitle;

            size_t ret = vlc_iconv( p_sys->iconv_handle,
                                    &psz_convert_buffer_in, &inbytes_left,
                                    &psz_convert_buffer_out, &outbytes_left );

            *psz_convert_buffer_out++ = '\0';
            free( psz_subtitle );

            if( ( ret == (size_t)(-1) ) || inbytes_left )
            {
                free( psz_new_subtitle );
                msg_Err( p_dec, "failed to convert subtitle encoding.\n"
                        "Try manually setting a character-encoding "
                                "before you open the file." );
                return NULL;
            }

            psz_subtitle = realloc( psz_new_subtitle,
                                    psz_convert_buffer_out - psz_new_subtitle );
            if( !psz_subtitle )
                psz_subtitle = psz_new_subtitle;
        }
    }

    /* Create the subpicture unit */
    p_spu = decoder_NewSubpicture( p_dec, NULL );
    if( !p_spu )
    {
        msg_Warn( p_dec, "can't get spu buffer" );
        free( psz_subtitle );
        return NULL;
    }

    /* Create a new subpicture region */
    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_TEXT;
    fmt.i_width = fmt.i_height = 0;
    fmt.i_x_offset = fmt.i_y_offset = 0;
    p_spu->p_region = subpicture_region_New( &fmt );
    if( !p_spu->p_region )
    {
        msg_Err( p_dec, "cannot allocate SPU region" );
        free( psz_subtitle );
        decoder_DeleteSubpicture( p_dec, p_spu );
        return NULL;
    }

    /* Decode and format the subpicture unit */
    if( p_dec->fmt_in.i_codec != VLC_CODEC_SSA )
    {
        /* Normal text subs, easy markup */
        p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM | p_sys->i_align;
        p_spu->p_region->i_x = p_sys->i_align ? 20 : 0;
        p_spu->p_region->i_y = 10;

        /* Remove formatting from string */

        p_spu->p_region->psz_text = StripTags( psz_subtitle );
        if( var_InheritBool( p_dec, "subsdec-formatted" ) )
        {
            p_spu->p_region->psz_html = CreateHtmlSubtitle( &p_spu->p_region->i_align, psz_subtitle );
        }

        p_spu->i_start = p_block->i_pts;
        p_spu->i_stop = p_block->i_pts + p_block->i_length;
        p_spu->b_ephemer = (p_block->i_length == 0);
        p_spu->b_absolute = false;
    }
    else
    {
        /* Decode SSA/USF strings */
        ParseSSAString( p_dec, psz_subtitle, p_spu );

        p_spu->i_start = p_block->i_pts;
        p_spu->i_stop = p_block->i_pts + p_block->i_length;
        p_spu->b_ephemer = (p_block->i_length == 0);
        p_spu->b_absolute = false;
        p_spu->i_original_picture_width = p_sys->i_original_width;
        p_spu->i_original_picture_height = p_sys->i_original_height;
    }
    free( psz_subtitle );

    return p_spu;
}