Beispiel #1
0
static subpicture_region_t * vout_OSDBackground(int x, int y,
                                                int width, int height,
                                                uint32_t i_argb)
{
    /* Create a new subpicture region */
    video_palette_t palette;
    spuregion_CreateVGradientPalette( &palette, GRADIENT_COLORS, i_argb, 0xFF000000 );

    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_YUVP);
    fmt.i_width  = fmt.i_visible_width  = width;
    fmt.i_height = fmt.i_visible_height = height;
    fmt.i_sar_num = 1;
    fmt.i_sar_den = 1;
    fmt.p_palette = &palette;

    subpicture_region_t *region = subpicture_region_New(&fmt);
    if (!region)
        return NULL;

    region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
    region->i_x = x;
    region->i_y = y;

    spuregion_CreateVGradientFill( region->p_picture->p, palette.i_entries );

    return region;
}
Beispiel #2
0
static subpicture_region_t * vout_OSDEpgText(const char *text,
                                             int x, int y,
                                             int size, uint32_t color)
{
    video_format_t fmt;
    subpicture_region_t *region;

    if (!text)
        return NULL;

    /* Create a new subpicture region */
    video_format_Init(&fmt, VLC_CODEC_TEXT);
    fmt.i_sar_num = 0;
    fmt.i_sar_den = 1;

    region = subpicture_region_New(&fmt);
    if (!region)
        return NULL;

    /* Set subpicture parameters */
    region->psz_text = strdup(text);
    region->i_align  = 0;
    region->i_x      = x;
    region->i_y      = y;

    /* Set text style */
    region->p_style = text_style_New();
    if (region->p_style) {
        region->p_style->i_font_size  = size;
        region->p_style->i_font_color = color;
        region->p_style->i_font_alpha = 0;
    }

    return region;
}
Beispiel #3
0
/**
 * Create a region with a white transparent picture.
 */
static subpicture_region_t *OSDRegion(int x, int y, int width, int height)
{
    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_YUVA);
    fmt.i_width          =
    fmt.i_visible_width  = width;
    fmt.i_height         =
    fmt.i_visible_height = height;
    fmt.i_sar_num        = 0;
    fmt.i_sar_den        = 1;

    subpicture_region_t *r = subpicture_region_New(&fmt);
    if (!r)
        return NULL;
    r->i_x = x;
    r->i_y = y;

    for (int i = 0; i < r->p_picture->i_planes; i++) {
        plane_t *p = &r->p_picture->p[i];
        int colors[PICTURE_PLANE_MAX] = {
            0xff, 0x80, 0x80, 0x00
        };
        memset(p->p_pixels, colors[i], p->i_pitch * height);
    }
    return r;
}
Beispiel #4
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;
}
Beispiel #5
0
/**
 * Create a region with a white transparent picture.
 */
static subpicture_region_t *OSDRegion(int x, int y, int width, int height)
{
    video_palette_t palette = {
	// sunqueen modify start
        /*.i_entries =*/ 2,
        /*.palette =*/ {
            /*[0] =*/ { 0xff, 0x80, 0x80, 0x00 },
            /*[1] =*/ { 0xff, 0x80, 0x80, 0xff },
        },
	// sunqueen modify end
    };

    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_YUVP);
    fmt.i_width          =
    fmt.i_visible_width  = width;
    fmt.i_height         =
    fmt.i_visible_height = height;
    fmt.i_sar_num        = 1;
    fmt.i_sar_den        = 1;
    fmt.p_palette        = &palette;

    subpicture_region_t *r = subpicture_region_New(&fmt);
    if (!r)
        return NULL;
    r->i_x = x;
    r->i_y = y;
    memset(r->p_picture->p->p_pixels, 0, r->p_picture->p->i_pitch * height);

    return r;
}
Beispiel #6
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=NULL;

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

    video_format_Init(&fmt, b_text ? VLC_CODEC_TEXT : VLC_CODEC_RGBA);
    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_sar_num = fmt.i_sar_den = 0; /* let the vout set the correct AR */
    }
    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" );
        subpicture_Delete( p_spu );
        return NULL;
    }

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

    p_spu->i_start = i_pts;
    p_spu->i_stop = b_text ? i_pts + (10*CLOCK_FREQ): 0;
    p_spu->b_ephemer = true;
    p_spu->b_absolute = b_text ? false : true;

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

    /* */
    *p_fmt = fmt;
    return p_spu;
}
static subpicture_region_t * vout_OSDEpgSlider(int x, int y,
                                               int width, int height,
                                               float ratio)
{
    /* Create a new subpicture region */
    video_palette_t palette = {
	// sunqueen modify start
        /*.i_entries =*/ 4,
        /*.palette =*/ {
            /*[0] =*/ { 0xff, 0x80, 0x80, 0x00 },
            /*[1] =*/ { 0x00, 0x80, 0x80, 0x00 },
            /*[2] =*/ { 0xff, 0x80, 0x80, 0xff },
            /*[3] =*/ { 0x00, 0x80, 0x80, 0xff },
        },
	// sunqueen modify end
    };

    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_YUVP);
    fmt.i_width  = fmt.i_visible_width  = width;
    fmt.i_height = fmt.i_visible_height = height;
    fmt.i_sar_num = 1;
    fmt.i_sar_den = 1;
    fmt.p_palette = &palette;

    subpicture_region_t *region = subpicture_region_New(&fmt);
    if (!region)
        return NULL;

    region->i_x = x;
    region->i_y = y;

    picture_t *picture = region->p_picture;

    ratio = VLC_CLIP(ratio, 0, 1);
    int filled_part_width = ratio * width;

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            /* Slider border. */
            bool is_outline = j == 0 || j == height - 1 ||
                              i == 0 || i == width  - 1;
            /* We can see the video through the part of the slider
               which corresponds to the leaving time. */
            bool is_border = j < 3 || j > height - 4 ||
                             i < 3 || i > width  - 4 ||
                             i < filled_part_width;

            picture->p->p_pixels[picture->p->i_pitch * j + i] = 2 * is_border + is_outline;
        }
    }

    return region;
}
Beispiel #8
0
static subpicture_region_t * vout_OSDEpgSlider( int i_x, int i_y,
                                                int i_width, int i_height,
                                                float f_ratio )
{
    video_format_t fmt;
    subpicture_region_t *p_region;

    /* Create a new subpicture region */
    video_format_Init( &fmt, VLC_CODEC_YUVA );
    fmt.i_width = fmt.i_visible_width = i_width;
    fmt.i_height = fmt.i_visible_height = i_height;
    fmt.i_sar_num = 0;
    fmt.i_sar_den = 1;

    p_region = subpicture_region_New( &fmt );
    if( !p_region )
        return NULL;

    p_region->i_x = i_x;
    p_region->i_y = i_y;

    picture_t *p_picture = p_region->p_picture;

    f_ratio = __MIN( __MAX( f_ratio, 0 ), 1 );
    int i_filled_part_width = f_ratio * i_width;

    for( int j = 0; j < i_height; j++ )
    {
        for( int i = 0; i < i_width; i++ )
        {
            #define WRITE_COMP( plane, value ) \
                p_picture->p[plane].p_pixels[p_picture->p[plane].i_pitch * j + i] = value

            /* Draw the slider. */
            bool is_outline = j == 0 || j == i_height - 1
                              || i == 0 || i == i_width - 1;
            WRITE_COMP( 0, is_outline ? 0x00 : 0xff );
            WRITE_COMP( 1, 0x80 );
            WRITE_COMP( 2, 0x80 );

            /* We can see the video through the part of the slider
               which corresponds to the leaving time. */
            bool is_border = j < 3 || j > i_height - 4
                             || i < 3 || i > i_width - 4
                             || i < i_filled_part_width;
            WRITE_COMP( 3, is_border ? 0xff : 0x00 );

            #undef WRITE_COMP
        }
    }

    return p_region;
}
Beispiel #9
0
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->psz_text = ParseText(payload,
                                            payload_size,
                                            cct_nums[dec->p_sys->cct - CCT_BEGIN].str);
        sub->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
        sub->p_region->psz_html = NULL;
    }

    free(payload);

exit:
    block_Release(b);
    return sub;
}
Beispiel #10
0
subpicture_t *subpicture_NewFromPicture( vlc_object_t *p_obj,
                                         picture_t *p_picture, vlc_fourcc_t i_chroma )
{
    /* */
    video_format_t fmt_in = p_picture->format;

    /* */
    video_format_t fmt_out;
    fmt_out = fmt_in;
    fmt_out.i_chroma = i_chroma;

    /* */
    image_handler_t *p_image = image_HandlerCreate( p_obj );
    if( !p_image )
        return NULL;

    picture_t *p_pip = image_Convert( p_image, p_picture, &fmt_in, &fmt_out );

    image_HandlerDelete( p_image );

    if( !p_pip )
        return NULL;

    subpicture_t *p_subpic = subpicture_New( NULL );
    if( !p_subpic )
    {
         picture_Release( p_pip );
         return NULL;
    }

    p_subpic->i_original_picture_width  = fmt_out.i_width;
    p_subpic->i_original_picture_height = fmt_out.i_height;

    fmt_out.i_sar_num =
    fmt_out.i_sar_den = 0;

    p_subpic->p_region = subpicture_region_New( &fmt_out );
    if( p_subpic->p_region )
    {
        picture_Release( p_subpic->p_region->p_picture );
        p_subpic->p_region->p_picture = p_pip;
    }
    else
    {
        picture_Release( p_pip );
    }
    return p_subpic;
}
/**
 * \brief Show text on the video from a given start date to a given end date
 * \param p_spu pointer to the subpicture queue the text is to be showed on
 * \param i_channel Subpicture channel
 * \param psz_string The text to be shown
 * \param p_style Pointer to a struct with text style info (it is duplicated)
 * \param i_flags flags for alignment and such
 * \param i_hmargin horizontal margin in pixels
 * \param i_vmargin vertical margin in pixels
 * \param i_start the time when this string is to appear on the video
 * \param i_stop the time when this string should stop to be displayed
 *               if this is 0 the string will be shown untill the next string
 *               is about to be shown
 */
int osd_ShowTextAbsolute( spu_t *p_spu_channel, int i_channel,
                           const char *psz_string, const text_style_t *p_style,
                           int i_flags, int i_hmargin, int i_vmargin,
                           mtime_t i_start, mtime_t i_stop )
{
    subpicture_t *p_spu;
    video_format_t fmt;
    (void)p_style;

    if( !psz_string ) return VLC_EGENERIC;

    p_spu = subpicture_New( NULL );
    if( !p_spu )
        return VLC_EGENERIC;

    p_spu->i_channel = i_channel;
    p_spu->i_start = i_start;
    p_spu->i_stop = i_stop;
    p_spu->b_ephemer = true;
    p_spu->b_absolute = false;

    /* 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_spu_channel, "cannot allocate SPU region" );
        subpicture_Delete( p_spu );
        return VLC_EGENERIC;
    }

    p_spu->p_region->psz_text = strdup( psz_string );
    p_spu->p_region->i_align = i_flags & SUBPICTURE_ALIGN_MASK;
    p_spu->p_region->i_x = i_hmargin;
    p_spu->p_region->i_y = i_vmargin;

    spu_PutSubpicture( p_spu_channel, p_spu );

    return VLC_SUCCESS;
}
Beispiel #12
0
subpicture_region_t* subpicture_region_Copy( subpicture_region_t *p_region_src )
{
    if (!p_region_src)
        return NULL;
    subpicture_region_t *p_region_dst = subpicture_region_New(&p_region_src->fmt);
    if (unlikely(!p_region_dst))
        return NULL;

    p_region_dst->i_x      = p_region_src->i_x;
    p_region_dst->i_y      = p_region_src->i_y;
    p_region_dst->i_align  = p_region_src->i_align;
    p_region_dst->i_alpha  = p_region_src->i_alpha;

    p_region_dst->p_text = text_segment_Copy( p_region_src->p_text );

    //Palette is already copied by subpicture_region_New, we just have to duplicate p_pixels
    for (int i = 0; i < p_region_src->p_picture->i_planes; i++)
        memcpy(p_region_dst->p_picture->p[i].p_pixels,
               p_region_src->p_picture->p[i].p_pixels,
               p_region_src->p_picture->p[i].i_lines * p_region_src->p_picture->p[i].i_pitch);
    return p_region_dst;
}
Beispiel #13
0
static subpicture_region_t * vout_OSDEpgText( const char *psz_string,
                                              int i_x, int i_y,
                                              int i_size, uint32_t i_color )
{
    video_format_t fmt;
    subpicture_region_t *p_region;

    if( !psz_string )
        return NULL;

    /* Create a new subpicture region */
    video_format_Init( &fmt, VLC_CODEC_TEXT );
    fmt.i_sar_num = 0;
    fmt.i_sar_den = 1;

    p_region = subpicture_region_New( &fmt );
    if( !p_region )
        return NULL;

    /* Set subpicture parameters */
    p_region->psz_text = strdup( psz_string );
    p_region->i_align = 0;
    p_region->i_x = i_x;
    p_region->i_y = i_y;

    /* Set text style */
    p_region->p_style = text_style_New();
    if( p_region->p_style )
    {
        p_region->p_style->i_font_size = i_size;
        p_region->p_style->i_font_color = i_color;
        p_region->p_style->i_font_alpha = 0;
    }

    return p_region;
}
Beispiel #14
0
/****************************************************************************
 * 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->b_need_update == false )
        goto out;

    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_aspect = 0;
    fmt.i_width = fmt.i_height = 0;
    fmt.i_x_offset = 0;
    fmt.i_y_offset = 0;
    p_spu->p_region = subpicture_region_New( &fmt );
    if( !p_spu->p_region )
    {
        p_filter->pf_sub_buffer_del( p_filter, p_spu );
        p_spu = NULL;
        goto out;
    }

    p_sys->last_time = date;

    if( !strchr( p_sys->psz_marquee, '%' )
     && !strchr( p_sys->psz_marquee, '$' ) )
        p_sys->b_need_update = false;

    p_spu->p_region->psz_text = str_format( p_filter, p_sys->psz_marquee );
    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 = OSD_ALIGN_LEFT | OSD_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_style = text_style_Duplicate( p_sys->p_style );

out:
    vlc_mutex_unlock( &p_sys->lock );
    return p_spu;
}
Beispiel #15
0
/****************************************************************************
 * 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;
    video_format_t fmt;
    subpicture_region_t *p_region;

    int i_feed, i_item;
    rss_feed_t *p_feed;

    memset( &fmt, 0, sizeof(video_format_t) );

    vlc_mutex_lock( &p_sys->lock );

    /* Check if the feeds have been fetched and that we have some feeds */
    /* TODO: check that we have items for each feeds */
    if( !p_sys->b_fetched && p_sys->i_feeds > 0 )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    if( p_sys->last_date
       + ( p_sys->i_cur_char == 0 && p_sys->i_cur_item == ( p_sys->i_title == scroll_title ? -1 : 0 ) ? 5 : 1 )
           /* ( ... ? 5 : 1 ) means "wait 5 times more for the 1st char" */
       * p_sys->i_speed > date )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    p_sys->last_date = date;
    p_sys->i_cur_char++;
    if( p_sys->i_cur_item == -1 ? p_sys->p_feeds[p_sys->i_cur_feed].psz_title[p_sys->i_cur_char] == 0 : p_sys->p_feeds[p_sys->i_cur_feed].p_items[p_sys->i_cur_item].psz_title[p_sys->i_cur_char] == 0 )
    {
        p_sys->i_cur_char = 0;
        p_sys->i_cur_item++;
        if( p_sys->i_cur_item >= p_sys->p_feeds[p_sys->i_cur_feed].i_items )
        {
            if( p_sys->i_title == scroll_title )
                p_sys->i_cur_item = -1;
            else
                p_sys->i_cur_item = 0;
            p_sys->i_cur_feed = (p_sys->i_cur_feed + 1)%p_sys->i_feeds;
        }
    }

    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    fmt.i_chroma = VLC_CODEC_TEXT;

    p_spu->p_region = subpicture_region_New( &fmt );
    if( !p_spu->p_region )
    {
        p_filter->pf_sub_buffer_del( p_filter, p_spu );
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    /* Generate the string that will be displayed. This string is supposed to
       be p_sys->i_length characters long. */
    i_item = p_sys->i_cur_item;
    i_feed = p_sys->i_cur_feed;
    p_feed = &p_sys->p_feeds[i_feed];

    if( ( p_feed->p_pic && p_sys->i_title == default_title )
        || p_sys->i_title == hide_title )
    {
        /* Don't display the feed's title if we have an image */
        _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s",
                  p_sys->p_feeds[i_feed].p_items[i_item].psz_title
                  +p_sys->i_cur_char );			// sunqueen modify
    }
    else if( ( !p_feed->p_pic && p_sys->i_title == default_title )
             || p_sys->i_title == prepend_title )
    {
        _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s : %s",
                  p_sys->p_feeds[i_feed].psz_title,
                  p_sys->p_feeds[i_feed].p_items[i_item].psz_title
                  +p_sys->i_cur_char );			// sunqueen modify
    }
    else /* scrolling title */
    {
        if( i_item == -1 )
            _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s : %s",
                      p_sys->p_feeds[i_feed].psz_title + p_sys->i_cur_char,
                      p_sys->p_feeds[i_feed].p_items[i_item+1].psz_title );			// sunqueen modify
        else
            _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s",
                      p_sys->p_feeds[i_feed].p_items[i_item].psz_title
                      +p_sys->i_cur_char );			// sunqueen modify
    }

    while( strlen( p_sys->psz_marquee ) < (unsigned int)p_sys->i_length )
    {
        i_item++;
        if( i_item == p_sys->p_feeds[i_feed].i_items ) break;
        _snprintf( strchr( p_sys->psz_marquee, 0 ),
                  p_sys->i_length - strlen( p_sys->psz_marquee ),
                  " - %s",
                  p_sys->p_feeds[i_feed].p_items[i_item].psz_title );			// sunqueen modify
    }

    /* Calls to snprintf might split multibyte UTF8 chars ...
     * which freetype doesn't like. */
    {
        char *a = strdup( p_sys->psz_marquee );
        char *a2 = a;
        char *b = p_sys->psz_marquee;
        EnsureUTF8( p_sys->psz_marquee );
        /* we want to use ' ' instead of '?' for erroneous chars */
        while( *b != '\0' )
        {
            if( *b != *a ) *b = ' ';
            b++;a++;
        }
        free( a2 );
    }

    p_spu->p_region->psz_text = strdup(p_sys->psz_marquee);
    if( p_sys->p_style->i_font_size > 0 )
        p_spu->p_region->fmt.i_visible_height = p_sys->p_style->i_font_size;
    p_spu->i_start = date;
    p_spu->i_stop  = 0;
    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_style = text_style_Duplicate( p_sys->p_style );

    if( p_feed->p_pic )
    {
        /* Display the feed's image */
        picture_t *p_pic = p_feed->p_pic;
        video_format_t fmt_out;

        memset( &fmt_out, 0, sizeof(video_format_t) );

        fmt_out.i_chroma = VLC_CODEC_YUVA;
        fmt_out.i_sar_num = fmt_out.i_sar_den = 1;
        fmt_out.i_width =
            fmt_out.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
        fmt_out.i_height =
            fmt_out.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;

        p_region = subpicture_region_New( &fmt_out );
        if( !p_region )
        {
            msg_Err( p_filter, "cannot allocate SPU region" );
        }
        else
        {
            p_region->i_x = p_spu->p_region->i_x;
            p_region->i_y = p_spu->p_region->i_y;
            /* FIXME the copy is probably not needed anymore */
            picture_Copy( p_region->p_picture, p_pic );
            p_spu->p_region->p_next = p_region;

            /* Offset text to display right next to the image */
            p_spu->p_region->i_x += fmt_out.i_visible_width;
        }
    }

    vlc_mutex_unlock( &p_sys->lock );
    return p_spu;
}
Beispiel #16
0
/**
 * Sub source
 */
static subpicture_t *FilterSub( filter_t *p_filter, mtime_t date )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    logo_list_t *p_list = &p_sys->list;

    subpicture_t *p_spu;
    subpicture_region_t *p_region;
    video_format_t fmt;
    picture_t *p_pic;
    logo_t *p_logo;

    vlc_mutex_lock( &p_sys->lock );
    /* Basic test:  b_spu_update occurs on a dynamic change,
                    & i_next_pic is the general timer, when to
                    look at updating the logo image */

    if( ( !p_sys->b_spu_update && p_list->i_next_pic > date ) ||
        !p_list->i_repeat )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    /* adjust index to the next logo */
    p_logo = LogoListNext( p_list, date );
    p_sys->b_spu_update = false;

    p_pic = p_logo->p_pic;

    /* Allocate the subpicture internal data. */
    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
        goto exit;

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

    /* Send an empty subpicture to clear the display when needed */
    if( p_list->i_repeat != -1 && p_list->i_counter == 0 )
    {
        p_list->i_repeat--;
        if( p_list->i_repeat == 0 )
            goto exit;
    }
    if( !p_pic || !p_logo->i_alpha ||
        ( p_logo->i_alpha == -1 && !p_list->i_alpha ) )
        goto exit;

    /* Create new SPU region */
    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_YUVA;
    fmt.i_sar_num = fmt.i_sar_den = 1;
    fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
    fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;
    fmt.i_x_offset = fmt.i_y_offset = 0;
    p_region = subpicture_region_New( &fmt );
    if( !p_region )
    {
        msg_Err( p_filter, "cannot allocate SPU region" );
        p_filter->pf_sub_buffer_del( p_filter, p_spu );
        p_spu = NULL;
        goto exit;
    }

    /* */
    picture_Copy( p_region->p_picture, p_pic );

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

    p_region->i_x = p_sys->i_pos_x;
    p_region->i_y = p_sys->i_pos_y;

    p_spu->p_region = p_region;

    p_spu->i_alpha = ( p_logo->i_alpha != -1 ?
                       p_logo->i_alpha : p_list->i_alpha );

exit:
    vlc_mutex_unlock( &p_sys->lock );

    return p_spu;
}
Beispiel #17
0
static void SubpictureUpdate( subpicture_t *p_subpic,
                              const video_format_t *p_fmt_src,
                              const video_format_t *p_fmt_dst,
                              mtime_t i_ts )
{
    VLC_UNUSED( p_fmt_src ); VLC_UNUSED( p_fmt_dst ); VLC_UNUSED( i_ts );

    decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;

    video_format_t fmt = p_sys->fmt;
    ASS_Image *p_img = p_subpic->updater.p_sys->p_img;

    /* */
    p_subpic->i_original_picture_height = fmt.i_visible_height;
    p_subpic->i_original_picture_width = fmt.i_visible_width;

    /* XXX to improve efficiency we merge regions that are close minimizing
     * the lost surface.
     * libass tends to create a lot of small regions and thus spu engine
     * reinstanciate a lot the scaler, and as we do not support subpel blending
     * it looks ugly (text unaligned).
     */
    const int i_max_region = 4;
    rectangle_t region[i_max_region];
    const int i_region = BuildRegions( region, i_max_region, p_img, fmt.i_width, fmt.i_height );

    if( i_region <= 0 )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return;
    }

    /* Allocate the regions and draw them */
    subpicture_region_t **pp_region_last = &p_subpic->p_region;

    for( int i = 0; i < i_region; i++ )
    {
        subpicture_region_t *r;
        video_format_t fmt_region;

        /* */
        fmt_region = fmt;
        fmt_region.i_width =
        fmt_region.i_visible_width  = region[i].x1 - region[i].x0;
        fmt_region.i_height =
        fmt_region.i_visible_height = region[i].y1 - region[i].y0;

        r = subpicture_region_New( &fmt_region );
        if( !r )
            break;
        r->i_x = region[i].x0;
        r->i_y = region[i].y0;
        r->i_align = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT;

        /* */
        RegionDraw( r, p_img );

        /* */
        *pp_region_last = r;
        pp_region_last = &r->p_next;
    }
    vlc_mutex_unlock( &p_sys->lock );

}
Beispiel #18
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, mtime_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 (%m)",
                      p_sys->psz_inputfile );
        }
        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 (%m)",
                          p_sys->psz_outputfile );
            }
        }
        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: %m" );
                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 = 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: %m" );
                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 = p_filter->pf_sub_buffer_new( p_filter );
    if( !p_spu )
    {
        msg_Err( p_filter, "cannot allocate subpicture" );
        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->psz_text = strdup( p_overlay->data.p_text );
            p_region->p_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;
}
Beispiel #19
0
/**
 * Sub source
 */
static subpicture_t *FilterSub( filter_t *p_filter, mtime_t date )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph);

    subpicture_t *p_spu;
    subpicture_region_t *p_region;
    video_format_t fmt;
    picture_t *p_pic;

    vlc_mutex_lock( &p_sys->lock );
    /* Basic test:  b_spu_update occurs on a dynamic change */
    if( !p_sys->b_spu_update )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return 0;
    }

    p_pic = p_BarGraph->p_pic;

    /* Allocate the subpicture internal data. */
    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
        goto exit;

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

    /* Send an empty subpicture to clear the display when needed */
    if( !p_pic || !p_BarGraph->i_alpha )
        goto exit;

    /* Create new SPU region */
    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_YUVA;
    fmt.i_sar_num = fmt.i_sar_den = 1;
    fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
    fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;
    fmt.i_x_offset = fmt.i_y_offset = 0;
    p_region = subpicture_region_New( &fmt );
    if( !p_region )
    {
        msg_Err( p_filter, "cannot allocate SPU region" );
        p_filter->pf_sub_buffer_del( p_filter, p_spu );
        p_spu = NULL;
        goto exit;
    }

    /* */
    picture_Copy( p_region->p_picture, p_pic );

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

    p_region->i_x = p_sys->i_pos_x;
    p_region->i_y = p_sys->i_pos_y;

    p_spu->p_region = p_region;

    p_spu->i_alpha = p_BarGraph->i_alpha ;

exit:
    vlc_mutex_unlock( &p_sys->lock );

    return p_spu;
}
Beispiel #20
0
/*****************************************************************************
 * Filter
 *****************************************************************************/
static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    bridge_t *p_bridge;

    subpicture_t *p_spu;

    int i_index, i_real_index, i_row, i_col;
    int i_greatest_real_index_used = p_sys->i_order_length - 1;

    unsigned int col_inner_width, row_inner_height;

    subpicture_region_t *p_region;
    subpicture_region_t *p_region_prev = NULL;

    /* Allocate the subpicture internal data. */
    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
        return NULL;

    /* Initialize subpicture */
    p_spu->i_channel = 0;
    p_spu->i_start  = date;
    p_spu->i_stop = 0;
    p_spu->b_ephemer = true;
    p_spu->i_alpha = p_sys->i_alpha;
    p_spu->b_absolute = false;

    vlc_mutex_lock( &p_sys->lock );
    vlc_global_lock( VLC_MOSAIC_MUTEX );

    p_bridge = GetBridge( p_filter );
    if ( p_bridge == NULL )
    {
        vlc_global_unlock( VLC_MOSAIC_MUTEX );
        vlc_mutex_unlock( &p_sys->lock );
        return p_spu;
    }

    if ( p_sys->i_position == position_offsets )
    {
        /* If we have either too much or not enough offsets, fall-back
         * to automatic positioning. */
        if ( p_sys->i_offsets_length != p_sys->i_order_length )
        {
            msg_Err( p_filter,
                     "Number of specified offsets (%d) does not match number "
                     "of input substreams in mosaic-order (%d), falling back "
                     "to mosaic-position=0",
                     p_sys->i_offsets_length, p_sys->i_order_length );
            p_sys->i_position = position_auto;
        }
    }

    if ( p_sys->i_position == position_auto )
    {
        int i_numpics = p_sys->i_order_length; /* keep slots and all */
        for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
        {
            bridged_es_t *p_es = p_bridge->pp_es[i_index];
            if ( !p_es->b_empty )
            {
                i_numpics ++;
                if( p_sys->i_order_length && p_es->psz_id != NULL )
                {
                    /* We also want to leave slots for images given in
                     * mosaic-order that are not available in p_vout_picture */
                    int i;
                    for( i = 0; i < p_sys->i_order_length ; i++ )
                    {
                        if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) )
                        {
                            i_numpics--;
                            break;
                        }
                    }

                }
            }
        }
        p_sys->i_rows = ceil(sqrt( (double)i_numpics ));
        p_sys->i_cols = ( i_numpics % p_sys->i_rows == 0 ?
                            i_numpics / p_sys->i_rows :
                            i_numpics / p_sys->i_rows + 1 );
    }

    col_inner_width  = ( ( p_sys->i_width - ( p_sys->i_cols - 1 )
                       * p_sys->i_borderw ) / p_sys->i_cols );
    row_inner_height = ( ( p_sys->i_height - ( p_sys->i_rows - 1 )
                       * p_sys->i_borderh ) / p_sys->i_rows );

    i_real_index = 0;

    for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ )
    {
        bridged_es_t *p_es = p_bridge->pp_es[i_index];
        video_format_t fmt_in, fmt_out;
        picture_t *p_converted;

        memset( &fmt_in, 0, sizeof( video_format_t ) );
        memset( &fmt_out, 0, sizeof( video_format_t ) );

        if ( p_es->b_empty )
            continue;

        while ( p_es->p_picture != NULL
                 && p_es->p_picture->date + p_sys->i_delay < date )
        {
            if ( p_es->p_picture->p_next != NULL )
            {
                picture_t *p_next = p_es->p_picture->p_next;
                picture_Release( p_es->p_picture );
                p_es->p_picture = p_next;
            }
            else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY <
                        date )
            {
                /* Display blank */
                picture_Release( p_es->p_picture );
                p_es->p_picture = NULL;
                p_es->pp_last = &p_es->p_picture;
                break;
            }
            else
            {
                msg_Dbg( p_filter, "too late picture for %s (%"PRId64 ")",
                         p_es->psz_id,
                         date - p_es->p_picture->date - p_sys->i_delay );
                break;
            }
        }

        if ( p_es->p_picture == NULL )
            continue;

        if ( p_sys->i_order_length == 0 )
        {
            i_real_index++;
        }
        else
        {
            int i;
            for ( i = 0; i <= p_sys->i_order_length; i++ )
            {
                if ( i == p_sys->i_order_length ) break;
                if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 )
                {
                    i_real_index = i;
                    break;
                }
            }
            if ( i == p_sys->i_order_length )
                i_real_index = ++i_greatest_real_index_used;
        }
        i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows;
        i_col = i_real_index % p_sys->i_cols ;

        if ( !p_sys->b_keep )
        {
            /* Convert the images */
            fmt_in.i_chroma = p_es->p_picture->format.i_chroma;
            fmt_in.i_height = p_es->p_picture->format.i_height;
            fmt_in.i_width = p_es->p_picture->format.i_width;

            if( fmt_in.i_chroma == VLC_CODEC_YUVA ||
                fmt_in.i_chroma == VLC_CODEC_RGBA )
                fmt_out.i_chroma = VLC_CODEC_YUVA;
            else
                fmt_out.i_chroma = VLC_CODEC_I420;
            fmt_out.i_width = col_inner_width;
            fmt_out.i_height = row_inner_height;

            if( p_sys->b_ar ) /* keep aspect ratio */
            {
                if( (float)fmt_out.i_width / (float)fmt_out.i_height
                      > (float)fmt_in.i_width / (float)fmt_in.i_height )
                {
                    fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width )
                                         / fmt_in.i_height;
                }
                else
                {
                    fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height )
                                        / fmt_in.i_width;
                }
             }

            fmt_out.i_visible_width = fmt_out.i_width;
            fmt_out.i_visible_height = fmt_out.i_height;

            p_converted = image_Convert( p_sys->p_image, p_es->p_picture,
                                         &fmt_in, &fmt_out );
            if( !p_converted )
            {
                msg_Warn( p_filter,
                           "image resizing and chroma conversion failed" );
                continue;
            }
        }
        else
        {
            p_converted = p_es->p_picture;
            fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width;
            fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height;
            fmt_in.i_chroma = fmt_out.i_chroma = p_converted->format.i_chroma;
            fmt_out.i_visible_width = fmt_out.i_width;
            fmt_out.i_visible_height = fmt_out.i_height;
        }

        p_region = subpicture_region_New( &fmt_out );
        /* FIXME the copy is probably not needed anymore */
        if( p_region )
            picture_Copy( p_region->p_picture, p_converted );
        if( !p_sys->b_keep )
            picture_Release( p_converted );

        if( !p_region )
        {
            msg_Err( p_filter, "cannot allocate SPU region" );
            p_filter->pf_sub_buffer_del( p_filter, p_spu );
            vlc_global_unlock( VLC_MOSAIC_MUTEX );
            vlc_mutex_unlock( &p_sys->lock );
            return p_spu;
        }

        if( p_es->i_x >= 0 && p_es->i_y >= 0 )
        {
            p_region->i_x = p_es->i_x;
            p_region->i_y = p_es->i_y;
        }
        else if( p_sys->i_position == position_offsets )
        {
            p_region->i_x = p_sys->pi_x_offsets[i_real_index];
            p_region->i_y = p_sys->pi_y_offsets[i_real_index];
        }
        else
        {
            if( fmt_out.i_width > col_inner_width ||
                p_sys->b_ar || p_sys->b_keep )
            {
                /* we don't have to center the video since it takes the
                whole rectangle area or it's larger than the rectangle */
                p_region->i_x = p_sys->i_xoffset
                            + i_col * ( p_sys->i_width / p_sys->i_cols )
                            + ( i_col * p_sys->i_borderw ) / p_sys->i_cols;
            }
            else
            {
                /* center the video in the dedicated rectangle */
                p_region->i_x = p_sys->i_xoffset
                        + i_col * ( p_sys->i_width / p_sys->i_cols )
                        + ( i_col * p_sys->i_borderw ) / p_sys->i_cols
                        + ( col_inner_width - fmt_out.i_width ) / 2;
            }

            if( fmt_out.i_height > row_inner_height
                || p_sys->b_ar || p_sys->b_keep )
            {
                /* we don't have to center the video since it takes the
                whole rectangle area or it's taller than the rectangle */
                p_region->i_y = p_sys->i_yoffset
                        + i_row * ( p_sys->i_height / p_sys->i_rows )
                        + ( i_row * p_sys->i_borderh ) / p_sys->i_rows;
            }
            else
            {
                /* center the video in the dedicated rectangle */
                p_region->i_y = p_sys->i_yoffset
                        + i_row * ( p_sys->i_height / p_sys->i_rows )
                        + ( i_row * p_sys->i_borderh ) / p_sys->i_rows
                        + ( row_inner_height - fmt_out.i_height ) / 2;
            }
        }
        p_region->i_align = p_sys->i_align;
        p_region->i_alpha = p_es->i_alpha;

        if( p_region_prev == NULL )
        {
            p_spu->p_region = p_region;
        }
        else
        {
            p_region_prev->p_next = p_region;
        }

        p_region_prev = p_region;
    }

    vlc_global_unlock( VLC_MOSAIC_MUTEX );
    vlc_mutex_unlock( &p_sys->lock );

    return p_spu;
}
Beispiel #21
0
/****************************************************************************
 * 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;
    subpicture_region_t *p_region;
    video_format_t fmt;
    picture_t *p_pic = NULL;

    vlc_mutex_lock( &p_sys->lock );

    if( p_sys->b_need_update )
        p_pic = p_sys->p_pic;

    if( p_pic == NULL )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    /* Allocate the subpicture internal data. */
    p_spu = filter_NewSubpicture( p_filter );
    if( !p_spu )
    {
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

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

    /* Create new SPU region */
    memset( &fmt, 0, sizeof(video_format_t) );
    fmt.i_chroma = VLC_CODEC_YUVA;
    fmt.i_sar_num = fmt.i_sar_den = 1;
    fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
    fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;
    fmt.i_x_offset = fmt.i_y_offset = 0;
    p_region = subpicture_region_New( &fmt );
    if( !p_region )
    {
        msg_Err( p_filter, "cannot allocate SPU region" );
        subpicture_Delete( p_spu );
        vlc_mutex_unlock( &p_sys->lock );
        return NULL;
    }

    /* FIXME the copy is probably not needed anymore */
    picture_Copy( p_region->p_picture, p_pic );

    p_sys->b_need_update = false;

    vlc_mutex_unlock( &p_sys->lock );

    /* set to one of the 9 relative locations */
    p_region->i_align = 0; /* Center */
    p_spu->b_absolute = false;


    p_spu->i_original_picture_width = 0; /*Let vout core do the horizontal scaling */
    p_spu->i_original_picture_height = fmt.i_height;

    p_spu->p_region = p_region;

    p_spu->i_alpha = ( p_sys->i_alpha );

    return p_spu;
}
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;

    /* 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_text_region->psz_text = NULL;
        p_text_region->psz_html = strndup( psz_subtitle, i_len );
        if( ! p_text_region->psz_html )
        {
            subpicture_region_Delete( p_text_region );
            return NULL;
        }

        p_ssa_style = ParseStyle( p_sys, p_text_region->psz_html );
        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->p_style = text_style_Duplicate( &p_ssa_style->font_style );
            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;

        }
        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;
        }
        /* 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;
}
Beispiel #23
0
/*****************************************************************************
 * 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;
}
Beispiel #24
0
/*****************************************************************************
 * 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;
}
Beispiel #25
0
/****************************************************************************
 * 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 = str_format_time( 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;
    p_spu->p_region = subpicture_region_New( &fmt );
    if( !p_spu->p_region )
    {
        p_filter->pf_sub_buffer_del( p_filter, p_spu );
        p_spu = NULL;
        goto out;
    }

    p_sys->last_time = date;

    p_spu->p_region->psz_text = strdup( 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_style = text_style_Duplicate( p_sys->p_style );

out:
    vlc_mutex_unlock( &p_sys->lock );
    return p_spu;
}
Beispiel #26
0
            [0] = { 0xff, 0x80, 0x80, 0x00 },
            [1] = { 0x00, 0x80, 0x80, 0x00 },
            [2] = { 0xff, 0x80, 0x80, 0xff },
            [3] = { 0x00, 0x80, 0x80, 0xff },
        },
    };

    video_format_t fmt;
    video_format_Init(&fmt, VLC_CODEC_YUVP);
    fmt.i_width  = fmt.i_visible_width  = width;
    fmt.i_height = fmt.i_visible_height = height;
    fmt.i_sar_num = 1;
    fmt.i_sar_den = 1;
    fmt.p_palette = &palette;

    subpicture_region_t *region = subpicture_region_New(&fmt);
    if (!region)
        return NULL;

    region->i_x = x;
    region->i_y = y;

    picture_t *picture = region->p_picture;

    ratio = VLC_CLIP(ratio, 0, 1);
    int filled_part_width = ratio * width;

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            /* Slider border. */
            bool is_outline = j == 0 || j == height - 1 ||
Beispiel #27
0
static subpicture_region_t *CreateTextRegion( decoder_t *p_dec,
                                              char *psz_subtitle,
                                              int i_sys_align )
{
    decoder_sys_t        *p_sys = p_dec->p_sys;
    subpicture_region_t  *p_text_region;
    video_format_t        fmt;

    /* Create a new subpicture region */
    video_format_Init( &fmt, 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 );
    video_format_Clean( &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 )
        {
            for( int 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];
            }
        }

        /* Set default or user align/magin.
         * Style overriden if no user value. */
        p_text_region->i_x = i_sys_align > 0 ? 20 : 0;
        p_text_region->i_y = 10;
        p_text_region->i_align = SUBPICTURE_ALIGN_BOTTOM |
                                 ((i_sys_align > 0) ? i_sys_align : 0);

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

            /* 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;
             */
            if( i_sys_align == -1 )
            {
                p_text_region->i_align     = p_ssa_style->i_align;
                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->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;
}