[vlc-commits] [Git][videolan/vlc][master] 2 commits: codec: libass: don't create spu for each split command

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Thu Jul 8 08:41:11 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
ffb4a94e by Francois Cartegnie at 2021-07-08T07:58:14+00:00
codec: libass: don't create spu for each split command

- - - - -
296e18b1 by Francois Cartegnie at 2021-07-08T07:58:14+00:00
codec: libass: speed up C blending, as for freetype

- - - - -


1 changed file:

- modules/codec/libass.c


Changes:

=====================================
modules/codec/libass.c
=====================================
@@ -76,6 +76,7 @@ static void Flush( decoder_t * );
 /* */
 typedef struct
 {
+    vlc_tick_t     i_last_pts;
     vlc_tick_t     i_max_stop;
 
     /* The following fields of decoder_sys_t are shared between decoder and spu units */
@@ -107,8 +108,6 @@ static void SubpictureDestroy( subpicture_t * );
 typedef struct
 {
     decoder_sys_t *p_dec_sys;
-    void          *p_subs_data;
-    int           i_subs_len;
     vlc_tick_t    i_pts;
 
     ASS_Image     *p_img;
@@ -148,7 +147,8 @@ static int Create( vlc_object_t *p_this )
     /* */
     vlc_mutex_init( &p_sys->lock );
     p_sys->i_refcount = 1;
-    memset( &p_sys->fmt, 0, sizeof(p_sys->fmt) );
+    video_format_Init( &p_sys->fmt, 0 );
+    p_sys->i_last_pts = VLC_TICK_INVALID;
     p_sys->i_max_stop = VLC_TICK_INVALID;
     p_sys->p_library  = NULL;
     p_sys->p_renderer = NULL;
@@ -332,6 +332,7 @@ static void Flush( decoder_t *p_dec )
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     p_sys->i_max_stop = VLC_TICK_INVALID;
+    p_sys->i_last_pts = VLC_TICK_INVALID;
 }
 
 /****************************************************************************
@@ -359,62 +360,59 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
         return VLCDEC_SUCCESS;
     }
 
-    libass_spu_updater_sys_t *p_spu_sys = malloc( sizeof(*p_spu_sys) );
-    if( !p_spu_sys )
+    if( p_block->i_pts != p_sys->i_last_pts )
     {
-        block_Release( p_block );
-        return VLCDEC_SUCCESS;
-    }
+        libass_spu_updater_sys_t *p_spu_sys = malloc( sizeof(*p_spu_sys) );
+        if( !p_spu_sys )
+        {
+            block_Release( p_block );
+            return VLCDEC_SUCCESS;
+        }
 
-    subpicture_updater_t updater = {
-        .pf_validate = SubpictureValidate,
-        .pf_update   = SubpictureUpdate,
-        .pf_destroy  = SubpictureDestroy,
-        .p_sys       = p_spu_sys,
-    };
-    p_spu = decoder_NewSubpicture( p_dec, &updater );
-    if( !p_spu )
-    {
-        msg_Warn( p_dec, "can't get spu buffer" );
-        free( p_spu_sys );
-        block_Release( p_block );
-        return VLCDEC_SUCCESS;
-    }
+        subpicture_updater_t updater = {
+            .pf_validate = SubpictureValidate,
+            .pf_update   = SubpictureUpdate,
+            .pf_destroy  = SubpictureDestroy,
+            .p_sys       = p_spu_sys,
+        };
 
-    p_spu_sys->p_img = NULL;
-    p_spu_sys->p_dec_sys = p_sys;
-    p_spu_sys->i_subs_len = p_block->i_buffer;
-    p_spu_sys->p_subs_data = malloc( p_block->i_buffer );
-    p_spu_sys->i_pts = p_block->i_pts;
-    if( !p_spu_sys->p_subs_data )
-    {
-        subpicture_Delete( p_spu );
-        block_Release( p_block );
-        return VLCDEC_SUCCESS;
-    }
-    memcpy( p_spu_sys->p_subs_data, p_block->p_buffer,
-            p_block->i_buffer );
+        p_spu = decoder_NewSubpicture( p_dec, &updater );
+        if( !p_spu )
+        {
+            msg_Warn( p_dec, "can't get spu buffer" );
+            free( p_spu_sys );
+            block_Release( p_block );
+            return VLCDEC_SUCCESS;
+        }
 
-    p_spu->i_start = p_block->i_pts;
-    p_spu->i_stop = __MAX( p_sys->i_max_stop, p_block->i_pts + p_block->i_length );
-    p_spu->b_ephemer = true;
-    p_spu->b_absolute = true;
+        p_spu_sys->p_img = NULL;
+        p_spu_sys->p_dec_sys = p_sys;
+        p_spu_sys->i_pts = p_block->i_pts;
+        p_spu->i_start = p_block->i_pts;
+        p_spu->i_stop = __MAX( p_sys->i_max_stop, p_block->i_pts + p_block->i_length );
+        p_spu->b_ephemer = true;
+        p_spu->b_absolute = true;
 
-    p_sys->i_max_stop = p_spu->i_stop;
+        p_sys->i_max_stop = p_spu->i_stop;
+
+        DecSysHold( p_sys ); /* Keep a reference for the returned subpicture */
+    }
+
+    p_sys->i_last_pts = p_block->i_pts;
 
     vlc_mutex_lock( &p_sys->lock );
     if( p_sys->p_track )
     {
-        ass_process_chunk( p_sys->p_track, p_spu_sys->p_subs_data, p_spu_sys->i_subs_len,
+        ass_process_chunk( p_sys->p_track,(void *) p_block->p_buffer, p_block->i_buffer,
                            MS_FROM_VLC_TICK( p_block->i_pts ), MS_FROM_VLC_TICK( p_block->i_length ) );
     }
     vlc_mutex_unlock( &p_sys->lock );
 
-    DecSysHold( p_sys ); /* Keep a reference for the returned subpicture */
-
     block_Release( p_block );
 
-    decoder_QueueSub( p_dec, p_spu );
+    if( p_spu )
+        decoder_QueueSub( p_dec, p_spu );
+
     return VLCDEC_SUCCESS;
 }
 
@@ -533,7 +531,6 @@ static void SubpictureDestroy( subpicture_t *p_subpic )
     libass_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
 
     DecSysRelease( p_spusys->p_dec_sys );
-    free( p_spusys->p_subs_data );
     free( p_spusys );
 }
 
@@ -699,49 +696,65 @@ static void RegionDraw( subpicture_region_t *p_region, ASS_Image *p_img )
     const int i_width  = p_region->fmt.i_width;
     const int i_height = p_region->fmt.i_height;
 
-    memset( p->p_pixels, 0x00, p->i_pitch * p->i_lines );
+    memset( p->p_pixels, 0x00, p->i_pitch * p->i_visible_lines );
     for( ; p_img != NULL; p_img = p_img->next )
     {
-        if( p_img->dst_x < i_x || p_img->dst_x + p_img->w > i_x + i_width ||
-            p_img->dst_y < i_y || p_img->dst_y + p_img->h > i_y + i_height )
+        int i_dst_x = p_img->dst_x - i_x;
+        int i_dst_y = p_img->dst_y - i_y;
+        if( i_dst_x < 0 || i_dst_x + p_img->w > i_width ||
+            i_dst_y < 0 || i_dst_y + p_img->h > i_height )
+            continue;
+
+        /* /!\ Bogus alpha channel is inverted */
+        const unsigned a = (~p_img->color      )&0xff;
+        if( a == 0 )
             continue;
 
         const unsigned r = (p_img->color >> 24)&0xff;
         const unsigned g = (p_img->color >> 16)&0xff;
         const unsigned b = (p_img->color >>  8)&0xff;
-        const unsigned a = (p_img->color      )&0xff;
-        int x, y;
 
-        for( y = 0; y < p_img->h; y++ )
-        {
-            for( x = 0; x < p_img->w; x++ )
-            {
-                const unsigned alpha = p_img->bitmap[y*p_img->stride+x];
-                const unsigned an = (255 - a) * alpha / 255;
+        const uint8_t *srcrow = p_img->bitmap;
+        int i_pitch_src = p_img->stride;
+        int i_pitch_dst = p->i_pitch;
+        uint8_t *dstrow = &p->p_pixels[i_dst_y * i_pitch_dst + 4 * i_dst_x];
 
-                uint8_t *p_rgba = &p->p_pixels[(y+p_img->dst_y-i_y) * p->i_pitch + 4 * (x+p_img->dst_x-i_x)];
-                const unsigned ao = p_rgba[3];
+        for( int y = 0; y < p_img->h; y++ )
+        {
+            const uint8_t *src = srcrow;
+            uint8_t *dst = dstrow;
 
-                /* Native endianness, but RGBA ordering */
-                if( ao == 0 )
-                {
-                    /* Optimized but the else{} will produce the same result */
-                    p_rgba[0] = r;
-                    p_rgba[1] = g;
-                    p_rgba[2] = b;
-                    p_rgba[3] = an;
-                }
-                else
+            for( int x = 0; x < p_img->w; x++ )
+            {
+                unsigned opacity = *src++; /* 1 Bpp channel */
+                if( opacity != 0 ) /* we need to blend only non transparent content */
                 {
-                    p_rgba[3] = 255 - ( 255 - p_rgba[3] ) * ( 255 - an ) / 255;
-                    if( p_rgba[3] != 0 )
+                    unsigned i_an = a * opacity / 255U;
+                    unsigned i_ao = dst[3];
+                    if( i_ao == 0 )
+                    {
+                        dst[0] = r;
+                        dst[1] = g;
+                        dst[2] = b;
+                        dst[3] = i_an;
+                    }
+                    else
                     {
-                        p_rgba[0] = ( p_rgba[0] * ao * (255-an) / 255 + r * an ) / p_rgba[3];
-                        p_rgba[1] = ( p_rgba[1] * ao * (255-an) / 255 + g * an ) / p_rgba[3];
-                        p_rgba[2] = ( p_rgba[2] * ao * (255-an) / 255 + b * an ) / p_rgba[3];
+                        unsigned i_ani = 255 - i_an;
+                        dst[3] = 255 - (255 - i_ao) * i_ani / 255;
+                        if( dst[3] != 0 )
+                        {
+                            unsigned i_aoni = i_ao * i_ani / 255;
+                            dst[0] = ( dst[0] * i_aoni + r * i_an ) / dst[3];
+                            dst[1] = ( dst[1] * i_aoni + g * i_an ) / dst[3];
+                            dst[2] = ( dst[2] * i_aoni + b * i_an ) / dst[3];
+                        }
                     }
                 }
+                dst += 4;
             }
+            srcrow += i_pitch_src;
+            dstrow += i_pitch_dst;
         }
     }
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/72d7150e61cb4ebcef586d110259b28b968943f6...296e18b19c189a4e7409e7a34f897bb21dfdc1fa

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/72d7150e61cb4ebcef586d110259b28b968943f6...296e18b19c189a4e7409e7a34f897bb21dfdc1fa
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list