Ejemplo n.º 1
0
Archivo: subsdec.c Proyecto: etix/vlc
static text_segment_t* NewTextSegmentPushStyle( text_segment_t* p_segment, style_stack_t** pp_stack )
{
    text_segment_t* p_new = text_segment_New( NULL );
    if ( unlikely( p_new == NULL ) )
        return NULL;
    text_style_t* p_style = DuplicateAndPushStyle( pp_stack );
    p_new->style = p_style;
    p_segment->p_next = p_new;
    return p_new;
}
Ejemplo n.º 2
0
Archivo: subsdec.c Proyecto: etix/vlc
static text_segment_t* NewTextSegmentPopStyle( text_segment_t* p_segment, style_stack_t** pp_stack )
{
    text_segment_t* p_new = text_segment_New( NULL );
    if ( unlikely( p_new == NULL ) )
        return NULL;
    // We shouldn't have an empty stack since this happens when closing a tag,
    // but better be safe than sorry if (/when) we encounter a broken subtitle file.
    PopStyle( pp_stack );
    text_style_t* p_dup = ( *pp_stack ) ? text_style_Duplicate( (*pp_stack)->p_style ) : text_style_Create( STYLE_NO_DEFAULTS );
    p_new->style = p_dup;
    p_segment->p_next = p_new;
    return p_new;
}
Ejemplo n.º 3
0
Archivo: stl.c Proyecto: 9034725985/vlc
static subpicture_t *Decode(decoder_t *dec, block_t **block)
{
    if (block == NULL || *block == NULL)
        return NULL;

    subpicture_t *sub = NULL;

    block_t *b = *block; *block = NULL;
    if (b->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED))
        goto exit;
    if (b->i_buffer < 128)
        goto exit;

    int     payload_size = (b->i_buffer / 128) * 112;
    uint8_t *payload = malloc(payload_size);
    if (!payload)
        goto exit;
    for (unsigned i = 0; i < b->i_buffer / 128; i++)
        memcpy(&payload[112 * i], &b->p_buffer[128 * i + 16], 112);

    sub = decoder_NewSubpicture(dec, NULL);
    if (!sub) {
        free(payload);
        goto exit;
    }
    sub->i_start    = b->i_pts;
    sub->i_stop     = b->i_pts + b->i_length;
    sub->b_ephemer  = b->i_length == 0;
    sub->b_absolute = false;
    //sub->i_original_picture_width  = 0;
    //sub->i_original_picture_height = 0;

    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_TEXT);
    sub->p_region = subpicture_region_New(&fmt);
    video_format_Clean(&fmt);

    if (sub->p_region) {
        sub->p_region->p_text = text_segment_New( ParseText(payload,
                                            payload_size,
                                            cct_nums[dec->p_sys->cct - CCT_BEGIN].str) );
        sub->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
    }

    free(payload);

exit:
    block_Release(b);
    return sub;
}
Ejemplo n.º 4
0
text_segment_t *text_segment_NewInheritStyle( const text_style_t* p_style )
{
    if ( !p_style )
        return NULL; //FIXME: Allow this, even if it is an alias to text_segment_New( NULL ) ?
    text_segment_t* p_segment = text_segment_New( NULL );
    if ( unlikely( !p_segment ) )
        return NULL;
    p_segment->style = text_style_Duplicate( p_style );
    if ( unlikely( !p_segment->style ) )
    {
        text_segment_Delete( p_segment );
        return NULL;
    }
    return p_segment;
}
Ejemplo n.º 5
0
Archivo: substx3g.c Proyecto: etix/vlc
static tx3g_segment_t * tx3g_segment_New( const char *psz_string )
{
    tx3g_segment_t *p_seg = malloc( sizeof(tx3g_segment_t) );
    if( p_seg )
    {
        p_seg->i_size = 0;
        p_seg->p_next3g = NULL;
        p_seg->s = text_segment_New( psz_string );
        if( !p_seg->s )
        {
            free( p_seg );
            p_seg = NULL;
        }
    }
    return p_seg;
}
Ejemplo n.º 6
0
text_segment_t *text_segment_Copy( text_segment_t *p_src )
{
    text_segment_t *p_dst = NULL, *p_dst0 = NULL;

    while( p_src ) {
        text_segment_t *p_new = text_segment_New( p_src->psz_text );
        if( p_new )
            p_new->style = text_style_Duplicate( p_src->style );

        if( p_dst == NULL )
        {
            p_dst = p_dst0 = p_new;
        }
        else
        {
            p_dst->p_next = p_new;
            p_dst = p_dst->p_next;
        }

        p_src = p_src->p_next;
    }

    return p_dst0;
}
Ejemplo n.º 7
0
Archivo: subsdec.c Proyecto: etix/vlc
static text_segment_t* ParseSubtitles( int *pi_align, const char *psz_subtitle )
{
    text_segment_t* p_segment;
    text_segment_t* p_first_segment;
    style_stack_t* p_stack = NULL;
    tag_stack_t* p_tag_stack = NULL;

    //FIXME: Remove initial allocation? Might make the below code more complicated
    p_first_segment = p_segment = text_segment_New( "" );

    bool b_has_align = false;

    /* */
    while( *psz_subtitle )
    {
        /* HTML extensions */
        if( *psz_subtitle == '<' )
        {
            char *psz_tagname = GetTag( &psz_subtitle, false );
            if ( psz_tagname != NULL )
            {
                if( !strcasecmp( psz_tagname, "br" ) )
                {
                    if ( !AppendCharacter( p_segment, '\n' ) )
                    {
                        free( psz_tagname );
                        goto fail;
                    }
                }
                else if( !strcasecmp( psz_tagname, "b" ) )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_BOLD;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                }
                else if( !strcasecmp( psz_tagname, "i" ) )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_ITALIC;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                }
                else if( !strcasecmp( psz_tagname, "u" ) )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_UNDERLINE;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                }
                else if( !strcasecmp( psz_tagname, "s" ) )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_STRIKEOUT;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                }
                else if( !strcasecmp( psz_tagname, "font" ) )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );

                    char* psz_attribute_name;
                    char* psz_attribute_value;

                    while( ( psz_attribute_name = ConsumeAttribute( &psz_subtitle, &psz_attribute_value ) ) )
                    {
                        if ( !strcasecmp( psz_attribute_name, "face" ) )
                        {
                            p_segment->style->psz_fontname = psz_attribute_value;
                            // We don't want to free the attribute value since it has become our fontname
                            psz_attribute_value = NULL;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "family" ) )
                        {
                            p_segment->style->psz_monofontname = psz_attribute_value;
                            psz_attribute_value = NULL;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "size" ) )
                        {
                            int size = atoi( psz_attribute_value );
                            if( size )
                            {
                                p_segment->style->i_font_size = size;
                                p_segment->style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
                                        STYLE_DEFAULT_FONT_SIZE / p_segment->style->i_font_size;
                            }
                        }
                        else if ( !strcasecmp( psz_attribute_name, "color" ) )
                        {
                            p_segment->style->i_font_color = vlc_html_color( psz_attribute_value, NULL );
                            p_segment->style->i_features |= STYLE_HAS_FONT_COLOR;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "outline-color" ) )
                        {
                            p_segment->style->i_outline_color = vlc_html_color( psz_attribute_value, NULL );
                            p_segment->style->i_features |= STYLE_HAS_OUTLINE_COLOR;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "shadow-color" ) )
                        {
                            p_segment->style->i_shadow_color = vlc_html_color( psz_attribute_value, NULL );
                            p_segment->style->i_features |= STYLE_HAS_SHADOW_COLOR;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "outline-level" ) )
                        {
                            p_segment->style->i_outline_width = atoi( psz_attribute_value );
                        }
                        else if ( !strcasecmp( psz_attribute_name, "shadow-level" ) )
                        {
                            p_segment->style->i_shadow_width = atoi( psz_attribute_value );
                        }
                        else if ( !strcasecmp( psz_attribute_name, "back-color" ) )
                        {
                            p_segment->style->i_background_color = vlc_html_color( psz_attribute_value, NULL );
                            p_segment->style->i_features |= STYLE_HAS_BACKGROUND_COLOR;
                        }
                        else if ( !strcasecmp( psz_attribute_name, "alpha" ) )
                        {
                            p_segment->style->i_font_alpha = atoi( psz_attribute_value );
                            p_segment->style->i_features |= STYLE_HAS_FONT_ALPHA;
                        }

                        free( psz_attribute_name );
                        free( psz_attribute_value );
                    }
                }
                else
                {
                    // This is an unknown tag. We need to hide it if it's properly closed, and display it otherwise
                    if ( !IsClosed( psz_subtitle, psz_tagname ) )
                    {
                        AppendCharacter( p_segment, '<' );
                        AppendString( p_segment, psz_tagname );
                        AppendCharacter( p_segment, '>' );
                    }
                    else
                    {
                        AppendTag( &p_tag_stack, psz_tagname );
                        // We don't want to free the tagname now, it will be freed when the tag
                        // gets poped from the stack.
                        psz_tagname = NULL;
                    }
                    // In any case, fall through and skip to the closing tag.
                }
                // Skip potential spaces & end tag
                while ( *psz_subtitle && *psz_subtitle != '>' )
                    psz_subtitle++;
                if ( *psz_subtitle == '>' )
                    psz_subtitle++;

                free( psz_tagname );
            }
            else if( !strncmp( psz_subtitle, "</", 2 ))
            {
                char* psz_tagname = GetTag( &psz_subtitle, true );
                if ( psz_tagname != NULL )
                {
                    if ( !strcasecmp( psz_tagname, "b" ) ||
                         !strcasecmp( psz_tagname, "i" ) ||
                         !strcasecmp( psz_tagname, "u" ) ||
                         !strcasecmp( psz_tagname, "s" ) ||
                         !strcasecmp( psz_tagname, "font" ) )
                    {
                        // A closing tag for one of the tags we handle, meaning
                        // we pushed a style onto the stack earlier
                        p_segment = NewTextSegmentPopStyle( p_segment, &p_stack );
                    }
                    else
                    {
                        // Unknown closing tag. If it is closing an unknown tag, ignore it. Otherwise, display it
                        if ( !HasTag( &p_tag_stack, psz_tagname ) )
                        {
                            AppendString( p_segment, "</" );
                            AppendString( p_segment, psz_tagname );
                            AppendCharacter( p_segment, '>' );
                        }
                    }
                    while ( *psz_subtitle == ' ' )
                        psz_subtitle++;
                    if ( *psz_subtitle == '>' )
                        psz_subtitle++;
                    free( psz_tagname );
                }
            }
            else
            {
                /* We have an unknown tag, just append it, and move on.
                 * The rest of the string won't be recognized as a tag, and
                 * we will ignore unknown closing tag
                 */
                AppendCharacter( p_segment, '<' );
                psz_subtitle++;
            }
        }
        /* SSA extensions */
        else if( psz_subtitle[0] == '{' && psz_subtitle[1] == '\\' &&
                 strchr( psz_subtitle, '}' ) )
        {
            /* Check for forced alignment */
            if( !b_has_align &&
                !strncmp( psz_subtitle, "{\\an", 4 ) && psz_subtitle[4] >= '1' && psz_subtitle[4] <= '9' && psz_subtitle[5] == '}' )
            {
                static const int pi_vertical[3] = { SUBPICTURE_ALIGN_BOTTOM, 0, SUBPICTURE_ALIGN_TOP };
                static const int pi_horizontal[3] = { SUBPICTURE_ALIGN_LEFT, 0, SUBPICTURE_ALIGN_RIGHT };
                const int i_id = psz_subtitle[4] - '1';

                b_has_align = true;
                *pi_align = pi_vertical[i_id/3] | pi_horizontal[i_id%3];
            }
            /* TODO fr -> rotation */

            /* Hide {\stupidity} */
            psz_subtitle = strchr( psz_subtitle, '}' ) + 1;
        }
        /* MicroDVD extensions */
        /* FIXME:
         *  - Currently, we don't do difference between X and x, and we should:
         *    Capital Letters applies to the whole text and not one line
         *  - We don't support Position and Coordinates
         *  - We don't support the DEFAULT flag (HEADER)
         */

        else if( psz_subtitle[0] == '{' &&
                 psz_subtitle[2] == ':' && strchr( &psz_subtitle[2], '}' ) )
        {
            const char *psz_tag_end = strchr( &psz_subtitle[2], '}' );
            size_t i_len = psz_tag_end - &psz_subtitle[3];

            if( psz_subtitle[1] == 'Y' || psz_subtitle[1] == 'y' )
            {
                if( psz_subtitle[3] == 'i' )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_ITALIC;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                    psz_subtitle++;
                }
                if( psz_subtitle[3] == 'b' )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_BOLD;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                    psz_subtitle++;
                }
                if( psz_subtitle[3] == 'u' )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_style_flags |= STYLE_UNDERLINE;
                    p_segment->style->i_features |= STYLE_HAS_FLAGS;
                    psz_subtitle++;
                }
            }
            else if( (psz_subtitle[1] == 'C' || psz_subtitle[1] == 'c' )
                    && psz_subtitle[3] == '$' && i_len >= 7 )
            {
                /* Yes, they use BBGGRR, instead of RRGGBB */
                char psz_color[7];
                psz_color[0] = psz_subtitle[8]; psz_color[1] = psz_subtitle[9];
                psz_color[2] = psz_subtitle[6]; psz_color[3] = psz_subtitle[7];
                psz_color[4] = psz_subtitle[4]; psz_color[5] = psz_subtitle[5];
                psz_color[6] = '\0';
                p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                p_segment->style->i_font_color = vlc_html_color( psz_color, NULL );
                p_segment->style->i_features |= STYLE_HAS_FONT_COLOR;
            }
            else if( psz_subtitle[1] == 'F' || psz_subtitle[1] == 'f' )
            {
                p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                p_segment->style->psz_fontname = strndup( &psz_subtitle[3], i_len );
            }
            else if( psz_subtitle[1] == 'S' || psz_subtitle[1] == 's' )
            {
                int size = atoi( &psz_subtitle[3] );
                if( size )
                {
                    p_segment = NewTextSegmentPushStyle( p_segment, &p_stack );
                    p_segment->style->i_font_size = size;
                    p_segment->style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
                                STYLE_DEFAULT_FONT_SIZE / p_segment->style->i_font_size;

                }
            }
            /* Currently unsupported since we don't have access to the i_align flag here
            else if( psz_subtitle[1] == 'P' )
            {
                if( psz_subtitle[3] == "1" )
                    i_align = SUBPICTURE_ALIGN_TOP;
                else if( psz_subtitle[3] == "0" )
                    i_align = SUBPICTURE_ALIGN_BOTTOM;
            } */
            // Hide other {x:y} atrocities, notably {o:x}
            psz_subtitle = psz_tag_end + 1;
        }
        else
        {
            if( *psz_subtitle == '\n' || !strncasecmp( psz_subtitle, "\\n", 2 ) )
            {
                if ( !AppendCharacter( p_segment, '\n' ) )
                    goto fail;
                if ( *psz_subtitle == '\n' )
                    psz_subtitle++;
                else
                    psz_subtitle += 2;
            }
            else if( !strncasecmp( psz_subtitle, "\\h", 2 ) )
            {
                if ( !AppendString( p_segment, "\xC2\xA0" ) )
                    goto fail;
                psz_subtitle += 2;
            }
            else
            {
                //FIXME: Highly inneficient
                AppendCharacter( p_segment, *psz_subtitle );
                psz_subtitle++;
            }
        }
    }
    while ( p_stack )
        PopStyle( &p_stack );
    while ( p_tag_stack )
    {
        tag_stack_t *p_tag = p_tag_stack;
        p_tag_stack = p_tag_stack->p_next;
        free( p_tag->psz_tagname );
        free( p_tag );
    }

    return p_first_segment;

fail:
    text_segment_ChainDelete( p_first_segment );
    return NULL;
}
Ejemplo n.º 8
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;

    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->p_segments = text_segment_New("");

            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];

        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->p_segments = text_segment_New( &p_text[offset] );
        if( p_spu_sys->p_segments && b_opaque )
        {
            p_spu_sys->p_segments->style = text_style_Create( STYLE_NO_DEFAULTS );
            if( p_spu_sys->p_segments->style )
            {
                /* Set text background */
                p_spu_sys->p_segments->style->i_style_flags = STYLE_BACKGROUND;
                p_spu_sys->p_segments->style->i_features |= STYLE_HAS_FLAGS;
            }
        }

        p_spu_sys->align = i_align;
        p_spu_sys->noregionbg = true;

#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
    }
    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 );
    block_Release( p_block );
    return NULL;
}
Ejemplo n.º 9
0
static subpicture_region_t *CreateTextRegion( decoder_t *p_dec,
                                              char *psz_subtitle,
                                              int i_len,
                                              int i_sys_align )
{
    decoder_sys_t        *p_sys = p_dec->p_sys;
    subpicture_region_t  *p_text_region;
    video_format_t        fmt;
    VLC_UNUSED( i_len );

    /* 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_text_region = subpicture_region_New( &fmt );

    if( p_text_region != NULL )
    {
        ssa_style_t  *p_ssa_style = NULL;

        p_ssa_style = ParseStyle( p_sys, psz_subtitle );
        if( !p_ssa_style )
        {
            int i;

            for( i = 0; i < p_sys->i_ssa_styles; i++ )
            {
                if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) )
                    p_ssa_style = p_sys->pp_ssa_styles[i];
            }
        }

        if( p_ssa_style )
        {
            msg_Dbg( p_dec, "style is: %s", p_ssa_style->psz_stylename );

            p_text_region->i_align = p_ssa_style->i_align;

            /* TODO: Setup % based offsets properly, without adversely affecting
             *       everything else in vlc. Will address with separate patch,
             *       to prevent this one being any more complicated.

                     * p_ssa_style->i_margin_percent_h;
                     * p_ssa_style->i_margin_percent_v;
             */
            p_text_region->i_x         = p_ssa_style->i_margin_h;
            p_text_region->i_y         = p_ssa_style->i_margin_v;
            p_text_region->p_text = text_segment_NewInheritStyle( p_ssa_style->p_style );
        }
        else
        {
            p_text_region->i_align = SUBPICTURE_ALIGN_BOTTOM | i_sys_align;
            p_text_region->i_x = i_sys_align ? 20 : 0;
            p_text_region->i_y = 10;
            p_text_region->p_text = text_segment_New( NULL );
        }
        /* Look for position arguments which may override the style-based
         * defaults.
         */
        SetupPositions( p_text_region, psz_subtitle );

        p_text_region->p_next = NULL;
    }
    return p_text_region;
}
Ejemplo n.º 10
0
/*****************************************************************************
 * Render: displays previously rendered output
 *****************************************************************************
 * This function send the currently rendered image to adjust modified image,
 * waits until it is displayed and switch the two rendering buffers, preparing
 * next frame.
 *****************************************************************************/
static subpicture_t *Filter( filter_t *p_filter, vlc_tick_t date )
{
    filter_sys_t *p_sys = p_filter->p_sys;

    /* We might need to open these at any time. */
    vlc_mutex_lock( &p_sys->lock );
    if( p_sys->i_inputfd == -1 )
    {
        p_sys->i_inputfd = vlc_open( p_sys->psz_inputfile, O_RDONLY | O_NONBLOCK );
        if( p_sys->i_inputfd == -1 )
        {
            msg_Warn( p_filter, "Failed to grab input file: %s (%s)",
                      p_sys->psz_inputfile, vlc_strerror_c(errno) );
        }
        else
        {
            msg_Info( p_filter, "Grabbed input file: %s",
                      p_sys->psz_inputfile );
        }
    }

    if( p_sys->i_outputfd == -1 )
    {
        p_sys->i_outputfd = vlc_open( p_sys->psz_outputfile,
                                  O_WRONLY | O_NONBLOCK );
        if( p_sys->i_outputfd == -1 )
        {
            if( errno != ENXIO )
            {
                msg_Warn( p_filter, "Failed to grab output file: %s (%s)",
                          p_sys->psz_outputfile, vlc_strerror_c(errno) );
            }
        }
        else
        {
            msg_Info( p_filter, "Grabbed output file: %s",
                      p_sys->psz_outputfile );
        }
    }
    vlc_mutex_unlock( &p_sys->lock );

    /* Read any waiting commands */
    if( p_sys->i_inputfd != -1 )
    {
        char p_buffer[1024];
        ssize_t i_len = read( p_sys->i_inputfd, p_buffer, 1024 );
        if( i_len == -1 )
        {
            /* We hit an error */
            if( errno != EAGAIN )
            {
                msg_Warn( p_filter, "Error on input file: %s",
                          vlc_strerror_c(errno) );
                vlc_close( p_sys->i_inputfd );
                p_sys->i_inputfd = -1;
            }
        }
        else if( i_len == 0 )
        {
            /* We hit the end-of-file */
        }
        else
        {
            BufferAdd( &p_sys->input, p_buffer, i_len );
        }
    }

    /* Parse any complete commands */
    char *p_end, *p_cmd;
    while( ( p_end = memchr( p_sys->input.p_begin, '\n',
                             p_sys->input.i_length ) ) )
    {
        commanddesc_t *p_cur = NULL;
        bool b_found = false;
        size_t i_index = 0;

        *p_end = '\0';
        p_cmd = BufferGetToken( &p_sys->input );

        msg_Info( p_filter, "Search command: %s", p_cmd );
        for( i_index = 0; i_index < p_sys->i_commands; i_index++ )
        {
            p_cur = p_sys->pp_commands[i_index];
            if( !strncmp( p_cur->psz_command, p_cmd, strlen(p_cur->psz_command) ) )
            {
                p_cmd[strlen(p_cur->psz_command)] = '\0';
                b_found = true;
                break;
            }
        }

        if( !b_found )
        {
            /* No matching command */
            msg_Err( p_filter, "Got invalid command: %s", p_cmd );
            BufferPrintf( &p_sys->output, "FAILURE: %d Invalid Command\n", VLC_EGENERIC );
        }
        else
        {
            msg_Info( p_filter, "Got valid command: %s", p_cmd );

            command_t *p_cmddesc = malloc( sizeof( command_t ) );
            if( !p_cmddesc )
                return NULL;

            p_cmd = p_cmd + strlen(p_cur->psz_command) +1;
            p_cmddesc->p_command = p_cur;
            p_cmddesc->p_command->pf_parser( p_cmd, p_end,
                                             &p_cmddesc->params );

            if( p_cmddesc->p_command->b_atomic && p_sys->b_atomic )
                QueueEnqueue( &p_sys->atomic, p_cmddesc );
            else
                QueueEnqueue( &p_sys->pending, p_cmddesc );
        }

        BufferDel( &p_sys->input, p_end - p_sys->input.p_begin + 1 );
    }

    /* Process any pending commands */
    command_t *p_command = NULL;
    while( (p_command = QueueDequeue( &p_sys->pending )) )
    {
        p_command->i_status =
            p_command->p_command->pf_execute( p_filter, &p_command->params,
                                              &p_command->results );
        QueueEnqueue( &p_sys->processed, p_command );
    }

    /* Output any processed commands */
    while( (p_command = QueueDequeue( &p_sys->processed )) )
    {
        if( p_command->i_status == VLC_SUCCESS )
        {
            const char *psz_success = "SUCCESS:";
            const char *psz_nl = "\n";
            BufferAdd( &p_sys->output, psz_success, 8 );
            p_command->p_command->pf_unparse( &p_command->results,
                                              &p_sys->output );
            BufferAdd( &p_sys->output, psz_nl, 1 );
        }
        else
        {
            BufferPrintf( &p_sys->output, "FAILURE: %d\n",
                          p_command->i_status );
        }
    }

    /* Try emptying the output buffer */
    if( p_sys->i_outputfd != -1 )
    {
        ssize_t i_len = vlc_write( p_sys->i_outputfd, p_sys->output.p_begin,
                                   p_sys->output.i_length );
        if( i_len == -1 )
        {
            /* We hit an error */
            if( errno != EAGAIN )
            {
                msg_Warn( p_filter, "Error on output file: %s",
                          vlc_strerror_c(errno) );
                vlc_close( p_sys->i_outputfd );
                p_sys->i_outputfd = -1;
            }
        }
        else
        {
            BufferDel( &p_sys->output, i_len );
        }
    }

    if( !p_sys->b_updated )
        return NULL;

    subpicture_t *p_spu = NULL;
    overlay_t *p_overlay = NULL;

    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
        return NULL;

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

    subpicture_region_t **pp_region = &p_spu->p_region;
    while( (p_overlay = ListWalk( &p_sys->overlays )) )
    {
        subpicture_region_t *p_region;

        *pp_region = p_region = subpicture_region_New( &p_overlay->format );
        if( !p_region )
            break;

        msg_Dbg( p_filter, "Displaying overlay: %4.4s, %d, %d, %d",
                 (char*)&p_overlay->format.i_chroma, p_overlay->i_x, p_overlay->i_y,
                 p_overlay->i_alpha );

        if( p_overlay->format.i_chroma == VLC_CODEC_TEXT )
        {
            p_region->p_text = text_segment_New( p_overlay->data.p_text );
            p_region->p_text->style = text_style_Duplicate( p_overlay->p_fontstyle );
        }
        else
        {
            /* FIXME the copy is probably not needed anymore */
            picture_Copy( p_region->p_picture, p_overlay->data.p_pic );
        }
        p_region->i_x = p_overlay->i_x;
        p_region->i_y = p_overlay->i_y;
        p_region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
        p_region->i_alpha = p_overlay->i_alpha;
        pp_region = &p_region->p_next;
    }

    p_sys->b_updated = false;
    return p_spu;
}
Ejemplo n.º 11
0
Archivo: marq.c Proyecto: 0xheart0/vlc
/****************************************************************************
 * Filter: the whole thing
 ****************************************************************************
 * This function outputs subpictures at regular time intervals.
 ****************************************************************************/
static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    subpicture_t *p_spu = NULL;
    video_format_t fmt;

    vlc_mutex_lock( &p_sys->lock );
    if( p_sys->last_time + p_sys->i_refresh > date )
        goto out;

    if( p_sys->filepath != NULL )
    {
        char *fmt = MarqueeReadFile( p_filter, p_sys->filepath );
        if( fmt != NULL )
        {
            free( p_sys->format );
            p_sys->format = fmt;
        }
    }

    char *msg = vlc_strftime( p_sys->format ? p_sys->format : "" );
    if( unlikely( msg == NULL ) )
        goto out;
    if( p_sys->message != NULL && !strcmp( msg, p_sys->message ) )
    {
        free( msg );
        goto out;
    }
    free( p_sys->message );
    p_sys->message = msg;

    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
        goto out;

    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_TEXT;
    fmt.i_width = fmt.i_height = 0;
    fmt.i_x_offset = 0;
    fmt.i_y_offset = 0;
    fmt.i_sar_den = fmt.i_sar_num = 1;
    p_spu->p_region = subpicture_region_New( &fmt );
    if( !p_spu->p_region )
    {
        subpicture_Delete( p_spu );
        p_spu = NULL;
        goto out;
    }

    p_sys->last_time = date;

    p_spu->p_region->p_text = text_segment_New( msg );
    p_spu->i_start = date;
    p_spu->i_stop  = p_sys->i_timeout == 0 ? 0 : date + p_sys->i_timeout * 1000;
    p_spu->b_ephemer = true;

    /*  where to locate the string: */
    if( p_sys->i_pos < 0 )
    {   /*  set to an absolute xy */
        p_spu->p_region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
        p_spu->b_absolute = true;
    }
    else
    {   /* set to one of the 9 relative locations */
        p_spu->p_region->i_align = p_sys->i_pos;
        p_spu->b_absolute = false;
    }

    p_spu->p_region->i_x = p_sys->i_xoff;
    p_spu->p_region->i_y = p_sys->i_yoff;

    p_spu->p_region->p_text->style = text_style_Duplicate( p_sys->p_style );

out:
    vlc_mutex_unlock( &p_sys->lock );
    return p_spu;
}