Changeset 35467e3f23ef35ac8fc8be8b2de57a3f9c53c826

Show
Ignore:
Timestamp:
19/10/07 00:10:11 (1 year ago)
Author:
Jean-Paul Saman <jpsaman@videolan.org>
git-committer:
Jean-Paul Saman <jpsaman@videolan.org> 1192745411 +0000
git-parent:

[6535c24d5e4b8b75fb47843655f830b32e57023b]

git-author:
Jean-Paul Saman <jpsaman@videolan.org> 1192745411 +0000
Message:

Add support for converting RGBA into YUVA using ffmpeg libswscale capabilities when available. This makes the Teletext subtitles streamable with dvbsub encoder/decoder.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/codec/zvbi.c

    r6e98a10 r35467e3  
    55 * $Id$ 
    66 * 
    7  * Authors: Derk-Jan Hartman <djhartman at m2x dot nl> for M2X 
     7 * Authors: Derk-Jan Hartman <djhartman at m2x dot nl> 
     8 *          Jean-Paul Saman <jpsaman at m2x dot nl> 
    89 * 
    910 * This program is free software; you can redistribute it and/or modify 
     
    130131    /* Positioning of Teletext images */ 
    131132    int                     i_align; 
     133 
     134    /* Misc */ 
     135#ifdef HAVE_FFMPEG_SWSCALE_H 
     136    image_handler_t         *p_image; 
     137#endif 
    132138}; 
    133139 
     
    135141static int RequestPage( vlc_object_t *p_this, char const *psz_cmd, 
    136142                        vlc_value_t oldval, vlc_value_t newval, void *p_data ); 
     143static int OpaquePage( decoder_t *p_dec, vbi_page p_page, video_format_t fmt, 
     144                        picture_t **p_src ); 
     145 
    137146static int Opaque( vlc_object_t *p_this, char const *psz_cmd, 
    138147                   vlc_value_t oldval, vlc_value_t newval, void *p_data ); 
     
    162171        msg_Err( p_dec, "out of memory" ); 
    163172        return VLC_ENOMEM; 
    164  
    165173    } 
    166174    memset( p_sys, 0, sizeof(decoder_sys_t) ); 
     175 
     176#ifdef HAVE_FFMPEG_SWSCALE_H 
     177    p_sys->p_image = image_HandlerCreate( VLC_OBJECT(p_dec) ); 
     178    if( !p_sys->p_image ) 
     179    { 
     180        free( p_sys ); 
     181        msg_Err( p_dec, "out of memory" ); 
     182        return VLC_ENOMEM; 
     183    } 
     184#endif 
    167185 
    168186    p_sys->p_vbi_dec = vbi_decoder_new(); 
     
    199217        p_dec->fmt_out.video.i_chroma = VLC_FOURCC('T','E','X','T'); 
    200218    else 
     219#ifdef HAVE_FFMPEG_SWSCALE_H 
     220        p_dec->fmt_out.video.i_chroma = VLC_FOURCC('Y','U','V','A'); 
     221#else 
    201222        p_dec->fmt_out.video.i_chroma = VLC_FOURCC('R','G','B','A'); 
    202  
     223#endif 
    203224    return VLC_SUCCESS; 
    204225} 
     
    212233    decoder_sys_t *p_sys = p_dec->p_sys; 
    213234 
     235#ifdef HAVE_FFMPEG_SWSCALE_H 
     236    if( p_sys->p_image ) image_HandlerDelete( p_sys->p_image ); 
     237#endif 
    214238    if( p_sys->p_vbi_dec ) vbi_decoder_delete( p_sys->p_vbi_dec ); 
    215239    if( p_sys->p_dvb_demux ) vbi_dvb_demux_delete( p_sys->p_dvb_demux ); 
     
    224248static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) 
    225249{ 
    226     decoder_sys_t   *p_sys = p_dec->p_sys; 
     250    decoder_sys_t   *p_sys = (decoder_sys_t *) p_dec->p_sys; 
    227251    block_t         *p_block; 
    228252    subpicture_t    *p_spu = NULL; 
     
    233257    unsigned int    i_left; 
    234258 
    235     /* part of kludge */ 
    236     uint32_t        *p_begin, *p_end; 
    237     unsigned        int x = 0, y = 0; 
    238     vbi_opacity     opacity; 
    239     /* end part of kludge */ 
    240  
    241259    if( (pp_block == NULL) || (*pp_block == NULL) ) 
    242260        return NULL; 
     
    275293    p_sys->i_last_page = p_sys->i_wanted_page; 
    276294    p_sys->b_update = VLC_FALSE; 
     295#if 0 
    277296    msg_Dbg( p_dec, "we now have page: %d ready for display", 
    278297             p_sys->i_wanted_page ); 
    279  
     298#endif 
    280299    /* If there is a page or sub to render, then we do that here */ 
    281300    /* Create the subpicture unit */ 
     
    289308    /* Create a new subpicture region */ 
    290309    memset( &fmt, 0, sizeof(video_format_t) ); 
    291     fmt.i_chroma = p_sys->b_text ? VLC_FOURCC('T','E','X','T') : VLC_FOURCC('R','G','B','A'); 
     310    fmt.i_chroma = p_sys->b_text ? VLC_FOURCC('T','E','X','T') : 
     311#ifdef HAVE_FFMPEG_SWSCALE_H 
     312                                   VLC_FOURCC('Y','U','V','A'); 
     313#else 
     314                                   VLC_FOURCC('R','G','B','A'); 
     315#endif 
    292316    fmt.i_aspect = p_sys->b_text ? 0 : VOUT_ASPECT_FACTOR; 
    293317    fmt.i_sar_num = fmt.i_sar_den = 1; 
     
    312336 
    313337    p_spu->i_start = (mtime_t) p_block->i_pts; 
    314     //msg_Dbg( p_dec, "spu start "I64Fd" pts "I64Fd, p_spu->i_start, p_block->i_pts ); 
    315338    p_spu->i_stop = (mtime_t) 0; 
    316339    p_spu->b_ephemer = VLC_TRUE; 
     
    322345    p_spu->i_original_picture_height = p_page.rows * 10; 
    323346 
     347#ifdef WORDS_BIGENDIAN 
     348# define ZVBI_PIXFMT_RGBA32 VBI_PIXFMT_RGBA32_BE 
     349#else 
     350# define ZVBI_PIXFMT_RGBA32 VBI_PIXFMT_RGBA32_LE 
     351#endif 
     352 
    324353    if( p_sys->b_text ) 
    325354    { 
     
    332361        p_text[i_total] = '\0'; 
    333362        /* Strip off the pagenumber */ 
    334         if( i_total <= 8 ) goto error; 
     363        if( i_total <= 40 ) goto error; 
    335364        p_spu->p_region->psz_text = strdup( &p_text[8] ); 
    336365 
     
    338367        msg_Dbg( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text ); 
    339368    } 
    340     else  
    341     { 
    342         vbi_draw_vt_page( &p_page, VBI_PIXFMT_RGBA32_LE, 
     369    else 
     370    { 
     371#ifdef HAVE_FFMPEG_SWSCALE_H 
     372        video_format_t fmt_in; 
     373        picture_t *p_pic, *p_dest; 
     374 
     375        p_pic = ( picture_t * ) malloc( sizeof( picture_t ) ); 
     376        if( !p_pic ) 
     377        { 
     378            msg_Err( p_dec, "out of memory" ); 
     379            goto error; 
     380        } 
     381 
     382        memset( &fmt_in, 0, sizeof( video_format_t ) ); 
     383        memset( p_pic, 0, sizeof( picture_t ) ); 
     384 
     385        fmt_in = p_spu->p_region->fmt; 
     386        fmt_in.i_chroma = VLC_FOURCC('R','G','B','A'); 
     387 
     388        vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic, fmt_in.i_chroma, 
     389                        fmt_in.i_width, fmt_in.i_height, fmt_in.i_aspect ); 
     390 
     391        if( !p_pic->i_planes ) 
     392        { 
     393            free( p_pic->p_data_orig ); 
     394            free( p_pic ); 
     395            goto error; 
     396        } 
     397 
     398        vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32, 
     399                          p_pic->p->p_pixels, 1, 1 ); 
     400 
     401        p_pic->p->i_lines = p_page.rows * 10; 
     402        p_pic->p->i_pitch = p_page.columns * 12 * 4; 
     403 
     404        OpaquePage( p_dec, p_page, fmt_in, &p_pic ); 
     405 
     406#if 0 
     407        msg_Dbg( p_dec, "page %x-%x(%d,%d)", 
     408                 p_page.pgno, p_page.subno, 
     409                 p_page.rows, p_page.columns ); 
     410#endif 
     411        p_dest = image_Convert( p_sys->p_image, p_pic, &fmt_in, 
     412                                &p_spu->p_region->fmt ); 
     413        if( !p_dest ) 
     414        { 
     415            free( p_pic->p_data_orig ); 
     416            free( p_pic ); 
     417            msg_Err( p_dec, "chroma conversion failed" ); 
     418            goto error; 
     419        } 
     420 
     421        vout_CopyPicture( VLC_OBJECT(p_dec), &p_spu->p_region->picture, 
     422                          p_dest ); 
     423 
     424        free( p_pic->p_data_orig ); 
     425        free( p_pic ); 
     426 
     427        free( p_dest->p_data_orig ); 
     428        free( p_dest ); 
     429#else 
     430        picture_t *p_pic; 
     431 
     432        vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32, 
    343433                          p_spu->p_region->picture.p->p_pixels, 1, 1 ); 
     434 
    344435        p_spu->p_region->picture.p->i_lines = p_page.rows * 10; 
    345436        p_spu->p_region->picture.p->i_pitch = p_page.columns * 12 * 4; 
    346     } 
    347  
    348     /* Kludge since zvbi doesn't provide an option to specify opacity. */ 
    349     if( p_sys->b_opaque && !p_sys->b_text ) 
    350     { 
    351         p_begin = (uint32_t *)p_spu->p_region->picture.p->p_pixels; 
    352         p_end   = (uint32_t *)p_spu->p_region->picture.p->p_pixels+(fmt.i_width * fmt.i_height); 
    353  
    354         for( ; p_begin < p_end; p_begin++ ) 
    355         { 
    356             opacity = p_page.text[ y / 10 * p_page.columns + x / 12 ].opacity; 
    357             switch( opacity ) 
    358             { 
    359             /* Show video instead of this character */ 
    360             case VBI_TRANSPARENT_SPACE: 
    361                 *p_begin = 0; 
    362                 break; 
    363             /* To make the boxed text "closed captioning" transparent 
    364              * change VLC_TRUE to VLC_FALSE. 
    365              */ 
    366             case VBI_OPAQUE: 
    367                 if( p_sys->b_opaque ) 
    368                     break; 
    369             /* Full text transparency. only foreground color is show */ 
    370             case VBI_TRANSPARENT_FULL: 
    371             /* Transparency for boxed text */ 
    372             case VBI_SEMI_TRANSPARENT: 
    373                 if( (*p_begin & 0xffffff00) == 0xff  ) 
    374                     *p_begin = 0; 
    375                 break; 
    376             default: 
    377                 break; 
    378             } 
    379             x++; 
    380             if( x >= fmt.i_width ) 
    381             { 
    382                 x = 0; 
    383                 y++; 
    384             } 
    385         } 
    386     } 
    387     /* end of kludge */ 
     437 
     438        p_pic = &(p_spu->p_region->picture); 
     439        OpaquePage( p_dec, p_page, fmt, &p_pic ); 
     440#endif 
     441    } 
     442 
     443#undef PIXFMT_RGBA32 
    388444 
    389445    vbi_unref_page( &p_page ); 
     
    432488} 
    433489 
     490static int OpaquePage( decoder_t *p_dec, vbi_page p_page, 
     491                       video_format_t fmt, picture_t **p_src ) 
     492{ 
     493    decoder_sys_t   *p_sys = (decoder_sys_t *) p_dec->p_sys; 
     494    uint32_t        *p_begin, *p_end; 
     495    unsigned        int x = 0, y = 0; 
     496    vbi_opacity     opacity; 
     497 
     498    /* Kludge since zvbi doesn't provide an option to specify opacity. */ 
     499    if( ( fmt.i_chroma != VLC_FOURCC('R','G','B','A' ) ) && 
     500        ( fmt.i_chroma != VLC_FOURCC('Y','U','V','A' ) ) ) 
     501    { 
     502        msg_Err( p_dec, "chroma not supported %4.4s", (char *)&fmt.i_chroma ); 
     503        return VLC_EGENERIC; 
     504    } 
     505 
     506    switch( fmt.i_chroma ) 
     507    { 
     508        case VLC_FOURCC('R','G','B','A' ): 
     509            p_begin = (uint32_t *)(*p_src)->p->p_pixels; 
     510            p_end = (uint32_t *)(*p_src)->p->p_pixels+(fmt.i_width * fmt.i_height); 
     511            break; 
     512        case VLC_FOURCC('Y','U','V','A' ): 
     513            p_begin = (uint32_t *)(*p_src)->p[A_PLANE].p_pixels; 
     514            p_end = (uint32_t *)(*p_src)->p[A_PLANE].p_pixels + 
     515                ( (*p_src)->p[A_PLANE].i_lines * (*p_src)->p[A_PLANE].i_pitch ); 
     516            break; 
     517        default: 
     518            msg_Err( p_dec, "chroma not supported %4.4s", (char *)&fmt.i_chroma ); 
     519            return VLC_EGENERIC; 
     520    } 
     521 
     522    for( ; p_begin < p_end; p_begin++ ) 
     523    { 
     524        opacity = p_page.text[ y / 10 * p_page.columns + x / 12 ].opacity; 
     525        switch( opacity ) 
     526        { 
     527        /* Show video instead of this character */ 
     528        case VBI_TRANSPARENT_SPACE: 
     529            *p_begin = 0; 
     530            break; 
     531        /* To make the boxed text "closed captioning" transparent 
     532         * change VLC_TRUE to VLC_FALSE. 
     533         */ 
     534        case VBI_OPAQUE: 
     535            if( p_sys->b_opaque ) 
     536                break; 
     537        /* Full text transparency. only foreground color is show */ 
     538        case VBI_TRANSPARENT_FULL: 
     539        /* Transparency for boxed text */ 
     540        case VBI_SEMI_TRANSPARENT: 
     541            if( (*p_begin & 0xffffff00) == 0xff  ) 
     542                *p_begin = 0; 
     543            break; 
     544        default: 
     545            break; 
     546        } 
     547        x++; 
     548        if( x >= fmt.i_width ) 
     549        { 
     550            x = 0; 
     551            y++; 
     552        } 
     553    } 
     554    /* end of kludge */ 
     555    return VLC_SUCCESS; 
     556} 
     557 
    434558static int RequestPage( vlc_object_t *p_this, char const *psz_cmd, 
    435559                        vlc_value_t oldval, vlc_value_t newval, void *p_data )