]> git.sesse.net Git - x264/blobdiff - common/frame.c
Periodic intra refresh
[x264] / common / frame.c
index 001c4fd9b7e20402cb74c0c7a6b316738e50ba64..0ece66917c9e2d464b01f85c312c729dc63c4f33 100644 (file)
@@ -53,8 +53,8 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
         frame->i_lines[i] = i_lines >> !!i;
     }
 
-    luma_plane_size = (frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ));
-    chroma_plane_size = (frame->i_stride[1] * ( frame->i_lines[1] + 2*i_padv ));
+    luma_plane_size = (frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv));
+    chroma_plane_size = (frame->i_stride[1] * (frame->i_lines[1] + 2*i_padv));
     for( i = 1; i < 3; i++ )
     {
         CHECKED_MALLOC( frame->buffer[i], chroma_plane_size );
@@ -73,22 +73,25 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
     frame->i_frame_num = -1;
     frame->i_lines_completed = -1;
     frame->b_fdec = b_fdec;
+    frame->orig = frame;
 
     /* all 4 luma planes allocated together, since the cacheline split code
      * requires them to be in-phase wrt cacheline alignment. */
     if( h->param.analyse.i_subpel_refine && b_fdec )
     {
-        CHECKED_MALLOC( frame->buffer[0], 4*luma_plane_size);
+        CHECKED_MALLOC( frame->buffer[0], 4*luma_plane_size );
         for( i = 0; i < 4; i++ )
             frame->filtered[i] = frame->buffer[0] + i*luma_plane_size + frame->i_stride[0] * i_padv + PADH;
         frame->plane[0] = frame->filtered[0];
     }
     else
     {
-        CHECKED_MALLOC( frame->buffer[0], luma_plane_size);
-        frame->plane[0] = frame->buffer[0] + frame->i_stride[0] * i_padv + PADH;
+        CHECKED_MALLOC( frame->buffer[0], luma_plane_size );
+        frame->filtered[0] = frame->plane[0] = frame->buffer[0] + frame->i_stride[0] * i_padv + PADH;
     }
 
+    frame->b_duplicate = 0;
+
     if( b_fdec ) /* fdec frame */
     {
         CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t));
@@ -121,7 +124,7 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
             frame->i_stride_lowres = ALIGN( frame->i_width_lowres + 2*PADH, align );
             frame->i_lines_lowres = frame->i_lines[0]/2;
 
-            luma_plane_size = frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv );
+            luma_plane_size = frame->i_stride_lowres * (frame->i_lines[0]/2 + 2*i_padv);
 
             CHECKED_MALLOC( frame->buffer_lowres[0], 4 * luma_plane_size );
             for( i = 0; i < 4; i++ )
@@ -168,38 +171,43 @@ fail:
 void x264_frame_delete( x264_frame_t *frame )
 {
     int i, j;
-    for( i = 0; i < 4; i++ )
-        x264_free( frame->buffer[i] );
-    for( i = 0; i < 4; i++ )
-        x264_free( frame->buffer_lowres[i] );
-    for( i = 0; i < X264_BFRAME_MAX+2; i++ )
-        for( j = 0; j < X264_BFRAME_MAX+2; j++ )
-            x264_free( frame->i_row_satds[i][j] );
-    for( j = 0; j < 2; j++ )
-        for( i = 0; i <= X264_BFRAME_MAX; i++ )
-        {
-            x264_free( frame->lowres_mvs[j][i] );
-            x264_free( frame->lowres_mv_costs[j][i] );
-        }
-    x264_free( frame->i_propagate_cost );
-    for( j = 0; j <= X264_BFRAME_MAX+1; j++ )
-        for( i = 0; i <= X264_BFRAME_MAX+1; i++ )
-        {
-            x264_free( frame->lowres_costs[j][i] );
-            x264_free( frame->lowres_inter_types[j][i] );
-        }
-    x264_free( frame->f_qp_offset );
-    x264_free( frame->f_qp_offset_aq );
-    x264_free( frame->i_inv_qscale_factor );
-    x264_free( frame->i_row_bits );
-    x264_free( frame->i_row_qp );
-    x264_free( frame->mb_type );
-    x264_free( frame->mv[0] );
-    x264_free( frame->mv[1] );
-    x264_free( frame->ref[0] );
-    x264_free( frame->ref[1] );
-    x264_pthread_mutex_destroy( &frame->mutex );
-    x264_pthread_cond_destroy( &frame->cv );
+    /* Duplicate frames are blank copies of real frames (including pointers),
+     * so freeing those pointers would cause a double free later. */
+    if( !frame->b_duplicate )
+    {
+        for( i = 0; i < 4; i++ )
+            x264_free( frame->buffer[i] );
+        for( i = 0; i < 4; i++ )
+            x264_free( frame->buffer_lowres[i] );
+        for( i = 0; i < X264_BFRAME_MAX+2; i++ )
+            for( j = 0; j < X264_BFRAME_MAX+2; j++ )
+                x264_free( frame->i_row_satds[i][j] );
+        for( j = 0; j < 2; j++ )
+            for( i = 0; i <= X264_BFRAME_MAX; i++ )
+            {
+                x264_free( frame->lowres_mvs[j][i] );
+                x264_free( frame->lowres_mv_costs[j][i] );
+            }
+        x264_free( frame->i_propagate_cost );
+        for( j = 0; j <= X264_BFRAME_MAX+1; j++ )
+            for( i = 0; i <= X264_BFRAME_MAX+1; i++ )
+            {
+                x264_free( frame->lowres_costs[j][i] );
+                x264_free( frame->lowres_inter_types[j][i] );
+            }
+        x264_free( frame->f_qp_offset );
+        x264_free( frame->f_qp_offset_aq );
+        x264_free( frame->i_inv_qscale_factor );
+        x264_free( frame->i_row_bits );
+        x264_free( frame->i_row_qp );
+        x264_free( frame->mb_type );
+        x264_free( frame->mv[0] );
+        x264_free( frame->mv[1] );
+        x264_free( frame->ref[0] );
+        x264_free( frame->ref[1] );
+        x264_pthread_mutex_destroy( &frame->mutex );
+        x264_pthread_cond_destroy( &frame->cv );
+    }
     x264_free( frame );
 }
 
@@ -215,7 +223,7 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
 
     dst->i_type     = src->i_type;
     dst->i_qpplus1  = src->i_qpplus1;
-    dst->i_pts      = src->i_pts;
+    dst->i_pts      = dst->i_dts = src->i_pts;
     dst->param      = src->param;
 
     for( i=0; i<3; i++ )
@@ -331,8 +339,8 @@ void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
         int i_subsample = i ? 1 : 0;
         int i_width = h->param.i_width >> i_subsample;
         int i_height = h->param.i_height >> i_subsample;
-        int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample;
-        int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample;
+        int i_padx = (h->sps->i_mb_width * 16 - h->param.i_width) >> i_subsample;
+        int i_pady = (h->sps->i_mb_height * 16 - h->param.i_height) >> i_subsample;
 
         if( i_padx )
         {
@@ -720,10 +728,10 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
         {\
             /* *** Get bS for each 4px for the current edge *** */\
             if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy]) )\
-                *(uint32_t*)bS = 0x03030303;\
+                M32( bS ) = 0x03030303;\
             else\
             {\
-                *(uint32_t*)bS = 0x00000000;\
+                M32( bS ) = 0x00000000;\
                 for( i = 0; i < 4; i++ )\
                 {\
                     int x  = i_dir == 0 ? i_edge : i;\
@@ -739,15 +747,20 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                             bS[i] = bS[i-1];\
                         else\
                         {\
-                            /* FIXME: A given frame may occupy more than one position in\
-                             * the reference list. So we should compare the frame numbers,\
-                             * not the indices in the ref list.\
-                             * No harm yet, as we don't generate that case.*/\
                             int i8p= mb_8x8+(x>>1)+(y>>1)*s8x8;\
                             int i8q= mbn_8x8+(xn>>1)+(yn>>1)*s8x8;\
                             int i4p= mb_4x4+x+y*s4x4;\
                             int i4q= mbn_4x4+xn+yn*s4x4;\
-                            if((h->mb.ref[0][i8p] != h->mb.ref[0][i8q] ||\
+                            int refs_equal;\
+                            /* We don't use duplicate refs in B-frames, so we can take this shortcut for now. */ \
+                            if( h->sh.i_type == SLICE_TYPE_B || h->mb.ref[0][i8p] < 0 || h->mb.ref[0][i8q] < 0 )\
+                                refs_equal = h->mb.ref[0][i8p] == h->mb.ref[0][i8q];\
+                            else if( !h->mb.b_interlaced )\
+                                refs_equal = h->fref0[h->mb.ref[0][i8p]]->i_poc == h->fref0[h->mb.ref[0][i8q]]->i_poc;\
+                            else\
+                                refs_equal = h->fref0[h->mb.ref[0][i8p]>>1]->i_poc == h->fref0[h->mb.ref[0][i8q]>>1]->i_poc\
+                                           && (h->mb.ref[0][i8p]&1) == (h->mb.ref[0][i8q]&1);\
+                            if((!refs_equal ||\
                                 abs( h->mb.mv[0][i4p][0] - h->mb.mv[0][i4q][0] ) >= 4 ||\
                                 abs( h->mb.mv[0][i4p][1] - h->mb.mv[0][i4q][1] ) >= mvy_limit ) ||\
                                (h->sh.i_type == SLICE_TYPE_B &&\
@@ -789,7 +802,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                     goto end##i_dir;\
                 }\
                 DEBLOCK_STRENGTH(i_dir);\
-                if( *(uint32_t*)bS )\
+                if( M32( bS ) )\
                     FILTER_DIR( , i_dir);\
                 end##i_dir:\
                 i_edge += b_8x8_transform+1;\
@@ -800,7 +813,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
             for( ; i_edge < i_edge_end; i_edge+=b_8x8_transform+1 )\
             {\
                 DEBLOCK_STRENGTH(i_dir);\
-                if( *(uint32_t*)bS )\
+                if( M32( bS ) )\
                     FILTER_DIR( , i_dir);\
             }\
         }
@@ -991,6 +1004,34 @@ x264_frame_t *x264_frame_pop_unused( x264_t *h, int b_fdec )
     frame->b_last_minigop_bframe = 0;
     frame->i_reference_count = 1;
     frame->b_intra_calculated = 0;
+    frame->b_scenecut = 1;
+    frame->b_keyframe = 0;
+
+    memset( frame->weight, 0, sizeof(frame->weight) );
+    memset( frame->f_weighted_cost_delta, 0, sizeof(frame->f_weighted_cost_delta) );
+
+    return frame;
+}
+
+void x264_frame_push_blank_unused( x264_t *h, x264_frame_t *frame )
+{
+    assert( frame->i_reference_count > 0 );
+    frame->i_reference_count--;
+    if( frame->i_reference_count == 0 )
+        x264_frame_push( h->frames.blank_unused, frame );
+}
+
+x264_frame_t *x264_frame_pop_blank_unused( x264_t *h )
+{
+    x264_frame_t *frame;
+    if( h->frames.blank_unused[0] )
+        frame = x264_frame_pop( h->frames.blank_unused );
+    else
+        frame = x264_malloc( sizeof(x264_frame_t) );
+    if( !frame )
+        return NULL;
+    frame->b_duplicate = 1;
+    frame->i_reference_count = 1;
     return frame;
 }
 
@@ -1014,9 +1055,27 @@ void x264_frame_sort( x264_frame_t **list, int b_dts )
     } while( !b_ok );
 }
 
+void x264_weight_scale_plane( x264_t *h, uint8_t *dst, int i_dst_stride, uint8_t *src, int i_src_stride,
+                         int i_width, int i_height, x264_weight_t *w )
+{
+    int x;
+    /* Weight horizontal strips of height 16. This was found to be the optimal height
+     * in terms of the cache loads. */
+    while( i_height > 0 )
+    {
+        for( x = 0; x < i_width; x += 16 )
+            w->weightfn[16>>2]( dst+x, i_dst_stride, src+x, i_src_stride, w, X264_MIN( i_height, 16 ) );
+        i_height -= 16;
+        dst += 16 * i_dst_stride;
+        src += 16 * i_src_stride;
+    }
+}
+
 void x264_frame_delete_list( x264_frame_t **list )
 {
     int i = 0;
+    if( !list )
+        return;
     while( list[i] )
         x264_frame_delete( list[i++] );
     x264_free( list );
@@ -1055,12 +1114,3 @@ void x264_synch_frame_list_push( x264_synch_frame_list_t *slist, x264_frame_t *f
     x264_pthread_mutex_unlock( &slist->mutex );
     x264_pthread_cond_broadcast( &slist->cv_fill );
 }
-
-int x264_synch_frame_list_get_size( x264_synch_frame_list_t *slist )
-{
-    int size;
-    x264_pthread_mutex_lock( &slist->mutex );
-    size = slist->i_size;
-    x264_pthread_mutex_unlock( &slist->mutex );
-    return size;
-}