2014-03-19 18:52:47 +03:00
/*
* H .26 L / H .264 / AVC / JVT / 14496 - 10 / . . . decoder
* Copyright ( c ) 2003 Michael Niedermayer < michaelni @ gmx . at >
*
2014-03-24 03:24:55 +03:00
* This file is part of FFmpeg .
2014-03-19 18:52:47 +03:00
*
2014-03-24 03:24:55 +03:00
* FFmpeg is free software ; you can redistribute it and / or
2014-03-19 18:52:47 +03:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
2014-03-24 03:24:55 +03:00
* FFmpeg is distributed in the hope that it will be useful ,
2014-03-19 18:52:47 +03:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2014-03-24 03:24:55 +03:00
* License along with FFmpeg ; if not , write to the Free Software
2014-03-19 18:52:47 +03:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
/**
* @ file
2016-04-27 19:45:23 +02:00
* H .264 / AVC / MPEG - 4 part10 codec .
2014-03-19 18:52:47 +03:00
* @ author Michael Niedermayer < michaelni @ gmx . at >
*/
# include "libavutil/avassert.h"
2016-05-18 07:27:32 +02:00
# include "libavutil/display.h"
2014-03-19 18:52:47 +03:00
# include "libavutil/imgutils.h"
2016-05-18 07:27:32 +02:00
# include "libavutil/stereo3d.h"
2014-03-19 18:52:47 +03:00
# include "libavutil/timer.h"
# include "internal.h"
# include "cabac.h"
# include "cabac_functions.h"
# include "error_resilience.h"
# include "avcodec.h"
# include "h264.h"
# include "h264data.h"
# include "h264chroma.h"
# include "h264_mvpred.h"
# include "golomb.h"
# include "mathops.h"
# include "mpegutils.h"
# include "rectangle.h"
# include "thread.h"
2014-03-24 03:24:55 +03:00
static const uint8_t field_scan [ 16 + 1 ] = {
2014-03-19 18:52:47 +03:00
0 + 0 * 4 , 0 + 1 * 4 , 1 + 0 * 4 , 0 + 2 * 4 ,
0 + 3 * 4 , 1 + 1 * 4 , 1 + 2 * 4 , 1 + 3 * 4 ,
2 + 0 * 4 , 2 + 1 * 4 , 2 + 2 * 4 , 2 + 3 * 4 ,
3 + 0 * 4 , 3 + 1 * 4 , 3 + 2 * 4 , 3 + 3 * 4 ,
} ;
2014-03-24 03:24:55 +03:00
static const uint8_t field_scan8x8 [ 64 + 1 ] = {
2014-03-19 18:52:47 +03:00
0 + 0 * 8 , 0 + 1 * 8 , 0 + 2 * 8 , 1 + 0 * 8 ,
1 + 1 * 8 , 0 + 3 * 8 , 0 + 4 * 8 , 1 + 2 * 8 ,
2 + 0 * 8 , 1 + 3 * 8 , 0 + 5 * 8 , 0 + 6 * 8 ,
0 + 7 * 8 , 1 + 4 * 8 , 2 + 1 * 8 , 3 + 0 * 8 ,
2 + 2 * 8 , 1 + 5 * 8 , 1 + 6 * 8 , 1 + 7 * 8 ,
2 + 3 * 8 , 3 + 1 * 8 , 4 + 0 * 8 , 3 + 2 * 8 ,
2 + 4 * 8 , 2 + 5 * 8 , 2 + 6 * 8 , 2 + 7 * 8 ,
3 + 3 * 8 , 4 + 1 * 8 , 5 + 0 * 8 , 4 + 2 * 8 ,
3 + 4 * 8 , 3 + 5 * 8 , 3 + 6 * 8 , 3 + 7 * 8 ,
4 + 3 * 8 , 5 + 1 * 8 , 6 + 0 * 8 , 5 + 2 * 8 ,
4 + 4 * 8 , 4 + 5 * 8 , 4 + 6 * 8 , 4 + 7 * 8 ,
5 + 3 * 8 , 6 + 1 * 8 , 6 + 2 * 8 , 5 + 4 * 8 ,
5 + 5 * 8 , 5 + 6 * 8 , 5 + 7 * 8 , 6 + 3 * 8 ,
7 + 0 * 8 , 7 + 1 * 8 , 6 + 4 * 8 , 6 + 5 * 8 ,
6 + 6 * 8 , 6 + 7 * 8 , 7 + 2 * 8 , 7 + 3 * 8 ,
7 + 4 * 8 , 7 + 5 * 8 , 7 + 6 * 8 , 7 + 7 * 8 ,
} ;
2014-03-24 03:24:55 +03:00
static const uint8_t field_scan8x8_cavlc [ 64 + 1 ] = {
2014-03-19 18:52:47 +03:00
0 + 0 * 8 , 1 + 1 * 8 , 2 + 0 * 8 , 0 + 7 * 8 ,
2 + 2 * 8 , 2 + 3 * 8 , 2 + 4 * 8 , 3 + 3 * 8 ,
3 + 4 * 8 , 4 + 3 * 8 , 4 + 4 * 8 , 5 + 3 * 8 ,
5 + 5 * 8 , 7 + 0 * 8 , 6 + 6 * 8 , 7 + 4 * 8 ,
0 + 1 * 8 , 0 + 3 * 8 , 1 + 3 * 8 , 1 + 4 * 8 ,
1 + 5 * 8 , 3 + 1 * 8 , 2 + 5 * 8 , 4 + 1 * 8 ,
3 + 5 * 8 , 5 + 1 * 8 , 4 + 5 * 8 , 6 + 1 * 8 ,
5 + 6 * 8 , 7 + 1 * 8 , 6 + 7 * 8 , 7 + 5 * 8 ,
0 + 2 * 8 , 0 + 4 * 8 , 0 + 5 * 8 , 2 + 1 * 8 ,
1 + 6 * 8 , 4 + 0 * 8 , 2 + 6 * 8 , 5 + 0 * 8 ,
3 + 6 * 8 , 6 + 0 * 8 , 4 + 6 * 8 , 6 + 2 * 8 ,
5 + 7 * 8 , 6 + 4 * 8 , 7 + 2 * 8 , 7 + 6 * 8 ,
1 + 0 * 8 , 1 + 2 * 8 , 0 + 6 * 8 , 3 + 0 * 8 ,
1 + 7 * 8 , 3 + 2 * 8 , 2 + 7 * 8 , 4 + 2 * 8 ,
3 + 7 * 8 , 5 + 2 * 8 , 4 + 7 * 8 , 5 + 4 * 8 ,
6 + 3 * 8 , 6 + 5 * 8 , 7 + 3 * 8 , 7 + 7 * 8 ,
} ;
// zigzag_scan8x8_cavlc[i] = zigzag_scan8x8[(i/4) + 16*(i%4)]
2014-03-24 03:24:55 +03:00
static const uint8_t zigzag_scan8x8_cavlc [ 64 + 1 ] = {
2014-03-19 18:52:47 +03:00
0 + 0 * 8 , 1 + 1 * 8 , 1 + 2 * 8 , 2 + 2 * 8 ,
4 + 1 * 8 , 0 + 5 * 8 , 3 + 3 * 8 , 7 + 0 * 8 ,
3 + 4 * 8 , 1 + 7 * 8 , 5 + 3 * 8 , 6 + 3 * 8 ,
2 + 7 * 8 , 6 + 4 * 8 , 5 + 6 * 8 , 7 + 5 * 8 ,
1 + 0 * 8 , 2 + 0 * 8 , 0 + 3 * 8 , 3 + 1 * 8 ,
3 + 2 * 8 , 0 + 6 * 8 , 4 + 2 * 8 , 6 + 1 * 8 ,
2 + 5 * 8 , 2 + 6 * 8 , 6 + 2 * 8 , 5 + 4 * 8 ,
3 + 7 * 8 , 7 + 3 * 8 , 4 + 7 * 8 , 7 + 6 * 8 ,
0 + 1 * 8 , 3 + 0 * 8 , 0 + 4 * 8 , 4 + 0 * 8 ,
2 + 3 * 8 , 1 + 5 * 8 , 5 + 1 * 8 , 5 + 2 * 8 ,
1 + 6 * 8 , 3 + 5 * 8 , 7 + 1 * 8 , 4 + 5 * 8 ,
4 + 6 * 8 , 7 + 4 * 8 , 5 + 7 * 8 , 6 + 7 * 8 ,
0 + 2 * 8 , 2 + 1 * 8 , 1 + 3 * 8 , 5 + 0 * 8 ,
1 + 4 * 8 , 2 + 4 * 8 , 6 + 0 * 8 , 4 + 3 * 8 ,
0 + 7 * 8 , 4 + 4 * 8 , 7 + 2 * 8 , 3 + 6 * 8 ,
5 + 5 * 8 , 6 + 5 * 8 , 6 + 6 * 8 , 7 + 7 * 8 ,
} ;
static void release_unused_pictures ( H264Context * h , int remove_current )
{
int i ;
/* release non reference frames */
for ( i = 0 ; i < H264_MAX_PICTURE_COUNT ; i + + ) {
2015-04-17 12:09:50 +02:00
if ( h - > DPB [ i ] . f - > buf [ 0 ] & & ! h - > DPB [ i ] . reference & &
2014-03-19 18:52:47 +03:00
( remove_current | | & h - > DPB [ i ] ! = h - > cur_pic_ptr ) ) {
ff_h264_unref_picture ( h , & h - > DPB [ i ] ) ;
}
}
}
2015-01-17 23:28:46 +02:00
static int alloc_scratch_buffers ( H264SliceContext * sl , int linesize )
2014-03-19 18:52:47 +03:00
{
2015-01-17 23:28:46 +02:00
const H264Context * h = sl - > h264 ;
2014-03-19 18:52:47 +03:00
int alloc_size = FFALIGN ( FFABS ( linesize ) + 32 , 32 ) ;
2015-01-17 23:28:46 +02:00
av_fast_malloc ( & sl - > bipred_scratchpad , & sl - > bipred_scratchpad_allocated , 16 * 6 * alloc_size ) ;
2014-03-19 18:52:47 +03:00
// edge emu needs blocksize + filter length - 1
2016-04-27 19:45:23 +02:00
// (= 21x21 for H.264)
2015-01-17 23:28:46 +02:00
av_fast_malloc ( & sl - > edge_emu_buffer , & sl - > edge_emu_buffer_allocated , alloc_size * 2 * 21 ) ;
2014-03-19 18:52:47 +03:00
2015-11-18 15:20:07 +02:00
av_fast_mallocz ( & sl - > top_borders [ 0 ] , & sl - > top_borders_allocated [ 0 ] ,
2015-01-17 23:28:46 +02:00
h - > mb_width * 16 * 3 * sizeof ( uint8_t ) * 2 ) ;
2015-11-18 15:20:07 +02:00
av_fast_mallocz ( & sl - > top_borders [ 1 ] , & sl - > top_borders_allocated [ 1 ] ,
2015-01-17 23:28:46 +02:00
h - > mb_width * 16 * 3 * sizeof ( uint8_t ) * 2 ) ;
if ( ! sl - > bipred_scratchpad | | ! sl - > edge_emu_buffer | |
! sl - > top_borders [ 0 ] | | ! sl - > top_borders [ 1 ] ) {
2015-01-17 23:28:46 +02:00
av_freep ( & sl - > bipred_scratchpad ) ;
av_freep ( & sl - > edge_emu_buffer ) ;
2015-01-17 23:28:46 +02:00
av_freep ( & sl - > top_borders [ 0 ] ) ;
av_freep ( & sl - > top_borders [ 1 ] ) ;
2015-01-17 23:28:46 +02:00
sl - > bipred_scratchpad_allocated = 0 ;
sl - > edge_emu_buffer_allocated = 0 ;
2015-01-17 23:28:46 +02:00
sl - > top_borders_allocated [ 0 ] = 0 ;
sl - > top_borders_allocated [ 1 ] = 0 ;
2014-03-19 18:52:47 +03:00
return AVERROR ( ENOMEM ) ;
}
return 0 ;
}
static int init_table_pools ( H264Context * h )
{
const int big_mb_num = h - > mb_stride * ( h - > mb_height + 1 ) + 1 ;
const int mb_array_size = h - > mb_stride * h - > mb_height ;
const int b4_stride = h - > mb_width * 4 + 1 ;
const int b4_array_size = b4_stride * h - > mb_height * 4 ;
h - > qscale_table_pool = av_buffer_pool_init ( big_mb_num + h - > mb_stride ,
av_buffer_allocz ) ;
h - > mb_type_pool = av_buffer_pool_init ( ( big_mb_num + h - > mb_stride ) *
sizeof ( uint32_t ) , av_buffer_allocz ) ;
2014-07-17 01:31:06 +03:00
h - > motion_val_pool = av_buffer_pool_init ( 2 * ( b4_array_size + 4 ) *
sizeof ( int16_t ) , av_buffer_allocz ) ;
h - > ref_index_pool = av_buffer_pool_init ( 4 * mb_array_size , av_buffer_allocz ) ;
2014-03-19 18:52:47 +03:00
if ( ! h - > qscale_table_pool | | ! h - > mb_type_pool | | ! h - > motion_val_pool | |
! h - > ref_index_pool ) {
av_buffer_pool_uninit ( & h - > qscale_table_pool ) ;
av_buffer_pool_uninit ( & h - > mb_type_pool ) ;
av_buffer_pool_uninit ( & h - > motion_val_pool ) ;
av_buffer_pool_uninit ( & h - > ref_index_pool ) ;
return AVERROR ( ENOMEM ) ;
}
return 0 ;
}
static int alloc_picture ( H264Context * h , H264Picture * pic )
{
int i , ret = 0 ;
2015-04-17 12:09:50 +02:00
av_assert0 ( ! pic - > f - > data [ 0 ] ) ;
2014-03-19 18:52:47 +03:00
2015-04-17 12:09:50 +02:00
pic - > tf . f = pic - > f ;
2014-03-19 18:52:47 +03:00
ret = ff_thread_get_buffer ( h - > avctx , & pic - > tf , pic - > reference ?
AV_GET_BUFFER_FLAG_REF : 0 ) ;
if ( ret < 0 )
goto fail ;
2016-06-12 13:24:27 +02:00
pic - > crop = h - > ps . sps - > crop ;
pic - > crop_top = h - > ps . sps - > crop_top ;
pic - > crop_left = h - > ps . sps - > crop_left ;
2014-03-19 18:52:47 +03:00
if ( h - > avctx - > hwaccel ) {
const AVHWAccel * hwaccel = h - > avctx - > hwaccel ;
av_assert0 ( ! pic - > hwaccel_picture_private ) ;
2014-03-06 20:19:52 +03:00
if ( hwaccel - > frame_priv_data_size ) {
pic - > hwaccel_priv_buf = av_buffer_allocz ( hwaccel - > frame_priv_data_size ) ;
2014-03-19 18:52:47 +03:00
if ( ! pic - > hwaccel_priv_buf )
return AVERROR ( ENOMEM ) ;
pic - > hwaccel_picture_private = pic - > hwaccel_priv_buf - > data ;
}
}
2015-07-27 21:14:31 +02:00
if ( CONFIG_GRAY & & ! h - > avctx - > hwaccel & & h - > flags & AV_CODEC_FLAG_GRAY & & pic - > f - > data [ 2 ] ) {
2014-03-24 03:24:55 +03:00
int h_chroma_shift , v_chroma_shift ;
2015-04-29 15:44:21 +02:00
av_pix_fmt_get_chroma_sub_sample ( pic - > f - > format ,
2014-03-24 03:24:55 +03:00
& h_chroma_shift , & v_chroma_shift ) ;
2016-01-27 17:19:38 +02:00
for ( i = 0 ; i < AV_CEIL_RSHIFT ( pic - > f - > height , v_chroma_shift ) ; i + + ) {
2015-04-29 15:44:21 +02:00
memset ( pic - > f - > data [ 1 ] + pic - > f - > linesize [ 1 ] * i ,
2016-01-27 17:19:38 +02:00
0x80 , AV_CEIL_RSHIFT ( pic - > f - > width , h_chroma_shift ) ) ;
2015-04-29 15:44:21 +02:00
memset ( pic - > f - > data [ 2 ] + pic - > f - > linesize [ 2 ] * i ,
2016-01-27 17:19:38 +02:00
0x80 , AV_CEIL_RSHIFT ( pic - > f - > width , h_chroma_shift ) ) ;
2014-03-24 03:24:55 +03:00
}
}
2014-03-19 18:52:47 +03:00
if ( ! h - > qscale_table_pool ) {
ret = init_table_pools ( h ) ;
if ( ret < 0 )
goto fail ;
}
pic - > qscale_table_buf = av_buffer_pool_get ( h - > qscale_table_pool ) ;
pic - > mb_type_buf = av_buffer_pool_get ( h - > mb_type_pool ) ;
if ( ! pic - > qscale_table_buf | | ! pic - > mb_type_buf )
goto fail ;
pic - > mb_type = ( uint32_t * ) pic - > mb_type_buf - > data + 2 * h - > mb_stride + 1 ;
pic - > qscale_table = pic - > qscale_table_buf - > data + 2 * h - > mb_stride + 1 ;
for ( i = 0 ; i < 2 ; i + + ) {
pic - > motion_val_buf [ i ] = av_buffer_pool_get ( h - > motion_val_pool ) ;
pic - > ref_index_buf [ i ] = av_buffer_pool_get ( h - > ref_index_pool ) ;
if ( ! pic - > motion_val_buf [ i ] | | ! pic - > ref_index_buf [ i ] )
goto fail ;
pic - > motion_val [ i ] = ( int16_t ( * ) [ 2 ] ) pic - > motion_val_buf [ i ] - > data + 4 ;
pic - > ref_index [ i ] = pic - > ref_index_buf [ i ] - > data ;
}
return 0 ;
fail :
ff_h264_unref_picture ( h , pic ) ;
return ( ret < 0 ) ? ret : AVERROR ( ENOMEM ) ;
}
static inline int pic_is_unused ( H264Context * h , H264Picture * pic )
{
2015-04-17 12:09:50 +02:00
if ( ! pic - > f - > buf [ 0 ] )
2014-03-19 18:52:47 +03:00
return 1 ;
return 0 ;
}
static int find_unused_picture ( H264Context * h )
{
int i ;
for ( i = 0 ; i < H264_MAX_PICTURE_COUNT ; i + + ) {
if ( pic_is_unused ( h , & h - > DPB [ i ] ) )
break ;
}
if ( i = = H264_MAX_PICTURE_COUNT )
return AVERROR_INVALIDDATA ;
return i ;
}
2015-06-27 23:56:06 +02:00
# define IN_RANGE(a, b, size) (((void*)(a) >= (void*)(b)) && ((void*)(a) < (void*)((b) + (size))))
2014-12-09 18:47:53 +02:00
2014-03-19 18:52:47 +03:00
# define REBASE_PICTURE(pic, new_ctx, old_ctx) \
2014-05-25 04:33:46 +03:00
( ( ( pic ) & & ( pic ) > = ( old_ctx ) - > DPB & & \
( pic ) < ( old_ctx ) - > DPB + H264_MAX_PICTURE_COUNT ) ? \
& ( new_ctx ) - > DPB [ ( pic ) - ( old_ctx ) - > DPB ] : NULL )
2014-03-19 18:52:47 +03:00
static void copy_picture_range ( H264Picture * * to , H264Picture * * from , int count ,
H264Context * new_base ,
H264Context * old_base )
{
int i ;
for ( i = 0 ; i < count ; i + + ) {
2015-06-27 23:56:41 +02:00
av_assert1 ( ! from [ i ] | |
IN_RANGE ( from [ i ] , old_base , 1 ) | |
IN_RANGE ( from [ i ] , old_base - > DPB , H264_MAX_PICTURE_COUNT ) ) ;
2014-03-19 18:52:47 +03:00
to [ i ] = REBASE_PICTURE ( from [ i ] , new_base , old_base ) ;
}
}
2015-04-12 19:36:49 +02:00
static int h264_slice_header_init ( H264Context * h ) ;
2014-03-19 18:52:47 +03:00
int ff_h264_update_thread_context ( AVCodecContext * dst ,
const AVCodecContext * src )
{
H264Context * h = dst - > priv_data , * h1 = src - > priv_data ;
int inited = h - > context_initialized , err = 0 ;
2015-04-06 20:05:37 +02:00
int need_reinit = 0 ;
2014-03-19 18:52:47 +03:00
int i , ret ;
2014-03-24 03:24:55 +03:00
if ( dst = = src )
2014-03-19 18:52:47 +03:00
return 0 ;
2016-06-12 13:24:27 +02:00
// We can't fail if SPS isn't set at it breaks current skip_frame code
//if (!h1->ps.sps)
// return AVERROR_INVALIDDATA;
2016-03-22 14:31:21 +02:00
2014-03-19 18:52:47 +03:00
if ( inited & &
( h - > width ! = h1 - > width | |
h - > height ! = h1 - > height | |
h - > mb_width ! = h1 - > mb_width | |
h - > mb_height ! = h1 - > mb_height | |
2016-03-22 14:31:21 +02:00
! h - > ps . sps | |
h - > ps . sps - > bit_depth_luma ! = h1 - > ps . sps - > bit_depth_luma | |
h - > ps . sps - > chroma_format_idc ! = h1 - > ps . sps - > chroma_format_idc | |
h - > ps . sps - > colorspace ! = h1 - > ps . sps - > colorspace ) ) {
2015-04-06 20:05:37 +02:00
need_reinit = 1 ;
2014-03-19 18:52:47 +03:00
}
2014-03-24 03:24:55 +03:00
/* copy block_offset since frame_start may not be called */
memcpy ( h - > block_offset , h1 - > block_offset , sizeof ( h - > block_offset ) ) ;
2014-03-19 18:52:47 +03:00
2015-04-12 20:59:52 +02:00
// SPS/PPS
2016-03-22 14:31:21 +02:00
for ( i = 0 ; i < FF_ARRAY_ELEMS ( h - > ps . sps_list ) ; i + + ) {
av_buffer_unref ( & h - > ps . sps_list [ i ] ) ;
if ( h1 - > ps . sps_list [ i ] ) {
h - > ps . sps_list [ i ] = av_buffer_ref ( h1 - > ps . sps_list [ i ] ) ;
if ( ! h - > ps . sps_list [ i ] )
return AVERROR ( ENOMEM ) ;
}
}
for ( i = 0 ; i < FF_ARRAY_ELEMS ( h - > ps . pps_list ) ; i + + ) {
av_buffer_unref ( & h - > ps . pps_list [ i ] ) ;
if ( h1 - > ps . pps_list [ i ] ) {
h - > ps . pps_list [ i ] = av_buffer_ref ( h1 - > ps . pps_list [ i ] ) ;
if ( ! h - > ps . pps_list [ i ] )
return AVERROR ( ENOMEM ) ;
}
}
2016-06-12 13:24:27 +02:00
av_buffer_unref ( & h - > ps . pps_ref ) ;
av_buffer_unref ( & h - > ps . sps_ref ) ;
h - > ps . pps = NULL ;
h - > ps . sps = NULL ;
if ( h1 - > ps . pps_ref ) {
h - > ps . pps_ref = av_buffer_ref ( h1 - > ps . pps_ref ) ;
if ( ! h - > ps . pps_ref )
return AVERROR ( ENOMEM ) ;
2016-06-12 21:28:10 +02:00
h - > ps . pps = ( const PPS * ) h - > ps . pps_ref - > data ;
2016-06-12 13:24:27 +02:00
}
if ( h1 - > ps . sps_ref ) {
h - > ps . sps_ref = av_buffer_ref ( h1 - > ps . sps_ref ) ;
if ( ! h - > ps . sps_ref )
return AVERROR ( ENOMEM ) ;
2016-06-21 14:17:13 +02:00
h - > ps . sps = ( const SPS * ) h - > ps . sps_ref - > data ;
2016-06-12 13:24:27 +02:00
}
2014-03-24 03:24:55 +03:00
2015-04-12 20:59:52 +02:00
if ( need_reinit | | ! inited ) {
h - > width = h1 - > width ;
h - > height = h1 - > height ;
h - > mb_height = h1 - > mb_height ;
h - > mb_width = h1 - > mb_width ;
h - > mb_num = h1 - > mb_num ;
h - > mb_stride = h1 - > mb_stride ;
h - > b_stride = h1 - > b_stride ;
2015-04-29 14:18:30 +02:00
if ( h - > context_initialized | | h1 - > context_initialized ) {
if ( ( err = h264_slice_header_init ( h ) ) < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR , " h264_slice_header_init() failed " ) ;
return err ;
}
2014-03-19 18:52:47 +03:00
}
2016-07-27 17:24:48 +02:00
2015-04-12 20:59:52 +02:00
/* copy block_offset since frame_start may not be called */
memcpy ( h - > block_offset , h1 - > block_offset , sizeof ( h - > block_offset ) ) ;
2014-03-19 18:52:47 +03:00
}
h - > avctx - > coded_height = h1 - > avctx - > coded_height ;
h - > avctx - > coded_width = h1 - > avctx - > coded_width ;
h - > avctx - > width = h1 - > avctx - > width ;
h - > avctx - > height = h1 - > avctx - > height ;
h - > coded_picture_number = h1 - > coded_picture_number ;
h - > first_field = h1 - > first_field ;
h - > picture_structure = h1 - > picture_structure ;
2016-05-17 15:07:23 +02:00
h - > mb_aff_frame = h1 - > mb_aff_frame ;
2014-03-19 18:52:47 +03:00
h - > droppable = h1 - > droppable ;
2015-06-09 23:38:26 +02:00
h - > backup_width = h1 - > backup_width ;
h - > backup_height = h1 - > backup_height ;
h - > backup_pix_fmt = h1 - > backup_pix_fmt ;
2014-03-19 18:52:47 +03:00
for ( i = 0 ; i < H264_MAX_PICTURE_COUNT ; i + + ) {
ff_h264_unref_picture ( h , & h - > DPB [ i ] ) ;
2015-04-17 12:09:50 +02:00
if ( h1 - > DPB [ i ] . f - > buf [ 0 ] & &
2014-03-19 18:52:47 +03:00
( ret = ff_h264_ref_picture ( h , & h - > DPB [ i ] , & h1 - > DPB [ i ] ) ) < 0 )
return ret ;
}
h - > cur_pic_ptr = REBASE_PICTURE ( h1 - > cur_pic_ptr , h , h1 ) ;
ff_h264_unref_picture ( h , & h - > cur_pic ) ;
2015-04-17 12:09:50 +02:00
if ( h1 - > cur_pic . f - > buf [ 0 ] ) {
2015-02-12 13:26:58 +02:00
ret = ff_h264_ref_picture ( h , & h - > cur_pic , & h1 - > cur_pic ) ;
if ( ret < 0 )
return ret ;
}
2014-03-19 18:52:47 +03:00
2015-03-31 10:35:15 +02:00
h - > enable_er = h1 - > enable_er ;
2014-03-19 18:52:47 +03:00
h - > workaround_bugs = h1 - > workaround_bugs ;
h - > droppable = h1 - > droppable ;
// extradata/NAL handling
h - > is_avc = h1 - > is_avc ;
2015-04-12 19:08:23 +02:00
h - > nal_length_size = h1 - > nal_length_size ;
2016-06-18 14:04:17 +02:00
h - > sei . unregistered . x264_build = h1 - > sei . unregistered . x264_build ;
2014-03-19 18:52:47 +03:00
2016-04-11 09:27:08 +02:00
memcpy ( & h - > poc , & h1 - > poc , sizeof ( h - > poc ) ) ;
2016-06-19 12:53:19 +02:00
memcpy ( h - > default_ref , h1 - > default_ref , sizeof ( h - > default_ref ) ) ;
2016-04-11 09:27:08 +02:00
memcpy ( h - > short_ref , h1 - > short_ref , sizeof ( h - > short_ref ) ) ;
memcpy ( h - > long_ref , h1 - > long_ref , sizeof ( h - > long_ref ) ) ;
memcpy ( h - > delayed_pic , h1 - > delayed_pic , sizeof ( h - > delayed_pic ) ) ;
memcpy ( h - > last_pocs , h1 - > last_pocs , sizeof ( h - > last_pocs ) ) ;
h - > next_output_pic = h1 - > next_output_pic ;
h - > next_outputed_poc = h1 - > next_outputed_poc ;
memcpy ( h - > mmco , h1 - > mmco , sizeof ( h - > mmco ) ) ;
2016-05-09 09:30:10 +02:00
h - > nb_mmco = h1 - > nb_mmco ;
2016-04-11 09:27:08 +02:00
h - > mmco_reset = h1 - > mmco_reset ;
2016-05-09 14:25:56 +02:00
h - > explicit_ref_marking = h1 - > explicit_ref_marking ;
2016-04-11 09:27:08 +02:00
h - > long_ref_count = h1 - > long_ref_count ;
h - > short_ref_count = h1 - > short_ref_count ;
2014-03-19 18:52:47 +03:00
copy_picture_range ( h - > short_ref , h1 - > short_ref , 32 , h , h1 ) ;
copy_picture_range ( h - > long_ref , h1 - > long_ref , 32 , h , h1 ) ;
copy_picture_range ( h - > delayed_pic , h1 - > delayed_pic ,
MAX_DELAYED_PIC_COUNT + 2 , h , h1 ) ;
2014-03-24 03:24:55 +03:00
h - > frame_recovered = h1 - > frame_recovered ;
2014-03-19 18:52:47 +03:00
if ( ! h - > cur_pic_ptr )
return 0 ;
if ( ! h - > droppable ) {
2016-05-09 14:25:56 +02:00
err = ff_h264_execute_ref_pic_marking ( h ) ;
2016-03-21 17:14:31 +02:00
h - > poc . prev_poc_msb = h - > poc . poc_msb ;
h - > poc . prev_poc_lsb = h - > poc . poc_lsb ;
2014-03-19 18:52:47 +03:00
}
2016-03-21 17:14:31 +02:00
h - > poc . prev_frame_num_offset = h - > poc . frame_num_offset ;
h - > poc . prev_frame_num = h - > poc . frame_num ;
2014-03-19 18:52:47 +03:00
h - > recovery_frame = h1 - > recovery_frame ;
return err ;
}
static int h264_frame_start ( H264Context * h )
{
H264Picture * pic ;
int i , ret ;
const int pixel_shift = h - > pixel_shift ;
2014-03-24 03:24:55 +03:00
int c [ 4 ] = {
2016-06-12 13:24:27 +02:00
1 < < ( h - > ps . sps - > bit_depth_luma - 1 ) ,
1 < < ( h - > ps . sps - > bit_depth_chroma - 1 ) ,
1 < < ( h - > ps . sps - > bit_depth_chroma - 1 ) ,
2014-03-24 03:24:55 +03:00
- 1
} ;
if ( ! ff_thread_can_start_frame ( h - > avctx ) ) {
av_log ( h - > avctx , AV_LOG_ERROR , " Attempt to start a frame outside SETUP state \n " ) ;
return - 1 ;
}
2014-03-19 18:52:47 +03:00
release_unused_pictures ( h , 1 ) ;
h - > cur_pic_ptr = NULL ;
i = find_unused_picture ( h ) ;
if ( i < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR , " no frame buffer available \n " ) ;
return i ;
}
pic = & h - > DPB [ i ] ;
pic - > reference = h - > droppable ? 0 : h - > picture_structure ;
2015-04-17 12:09:50 +02:00
pic - > f - > coded_picture_number = h - > coded_picture_number + + ;
2014-03-19 18:52:47 +03:00
pic - > field_picture = h - > picture_structure ! = PICT_FRAME ;
2016-03-21 17:14:31 +02:00
pic - > frame_num = h - > poc . frame_num ;
2014-03-19 18:52:47 +03:00
/*
* Zero key_frame here ; IDR markings per slice in frame or fields are ORed
* in later .
* See decode_nal_units ( ) .
*/
2015-04-17 12:09:50 +02:00
pic - > f - > key_frame = 0 ;
2014-03-19 18:52:47 +03:00
pic - > mmco_reset = 0 ;
pic - > recovered = 0 ;
2014-03-24 03:24:55 +03:00
pic - > invalid_gap = 0 ;
2016-06-18 14:04:17 +02:00
pic - > sei_recovery_frame_cnt = h - > sei . recovery_point . recovery_frame_cnt ;
2014-03-19 18:52:47 +03:00
2016-04-11 16:32:02 +02:00
pic - > f - > pict_type = h - > slice_ctx [ 0 ] . slice_type ;
2014-03-19 18:52:47 +03:00
if ( ( ret = alloc_picture ( h , pic ) ) < 0 )
return ret ;
2015-08-17 01:35:59 +02:00
if ( ! h - > frame_recovered & & ! h - > avctx - > hwaccel
# if FF_API_CAP_VDPAU
& & ! ( h - > avctx - > codec - > capabilities & AV_CODEC_CAP_HWACCEL_VDPAU )
# endif
)
2015-10-14 01:42:10 +02:00
ff_color_frame ( pic - > f , c ) ;
2014-03-19 18:52:47 +03:00
h - > cur_pic_ptr = pic ;
ff_h264_unref_picture ( h , & h - > cur_pic ) ;
2014-03-24 03:24:55 +03:00
if ( CONFIG_ERROR_RESILIENCE ) {
2015-03-21 21:00:34 +02:00
ff_h264_set_erpic ( & h - > slice_ctx [ 0 ] . er . cur_pic , NULL ) ;
2014-03-24 03:24:55 +03:00
}
2014-03-19 18:52:47 +03:00
if ( ( ret = ff_h264_ref_picture ( h , & h - > cur_pic , h - > cur_pic_ptr ) ) < 0 )
return ret ;
2015-03-22 00:45:46 +02:00
for ( i = 0 ; i < h - > nb_slice_ctx ; i + + ) {
2015-04-29 15:44:21 +02:00
h - > slice_ctx [ i ] . linesize = h - > cur_pic_ptr - > f - > linesize [ 0 ] ;
h - > slice_ctx [ i ] . uvlinesize = h - > cur_pic_ptr - > f - > linesize [ 1 ] ;
2015-03-22 00:45:46 +02:00
}
2015-04-04 00:49:57 +02:00
if ( CONFIG_ERROR_RESILIENCE & & h - > enable_er ) {
2015-01-17 23:28:46 +02:00
ff_er_frame_start ( & h - > slice_ctx [ 0 ] . er ) ;
2015-03-21 21:00:34 +02:00
ff_h264_set_erpic ( & h - > slice_ctx [ 0 ] . er . last_pic , NULL ) ;
ff_h264_set_erpic ( & h - > slice_ctx [ 0 ] . er . next_pic , NULL ) ;
2014-03-24 03:24:55 +03:00
}
2014-03-19 18:52:47 +03:00
for ( i = 0 ; i < 16 ; i + + ) {
2015-04-17 12:09:50 +02:00
h - > block_offset [ i ] = ( 4 * ( ( scan8 [ i ] - scan8 [ 0 ] ) & 7 ) < < pixel_shift ) + 4 * pic - > f - > linesize [ 0 ] * ( ( scan8 [ i ] - scan8 [ 0 ] ) > > 3 ) ;
h - > block_offset [ 48 + i ] = ( 4 * ( ( scan8 [ i ] - scan8 [ 0 ] ) & 7 ) < < pixel_shift ) + 8 * pic - > f - > linesize [ 0 ] * ( ( scan8 [ i ] - scan8 [ 0 ] ) > > 3 ) ;
2014-03-19 18:52:47 +03:00
}
for ( i = 0 ; i < 16 ; i + + ) {
h - > block_offset [ 16 + i ] =
2015-04-17 12:09:50 +02:00
h - > block_offset [ 32 + i ] = ( 4 * ( ( scan8 [ i ] - scan8 [ 0 ] ) & 7 ) < < pixel_shift ) + 4 * pic - > f - > linesize [ 1 ] * ( ( scan8 [ i ] - scan8 [ 0 ] ) > > 3 ) ;
2014-03-19 18:52:47 +03:00
h - > block_offset [ 48 + 16 + i ] =
2015-04-17 12:09:50 +02:00
h - > block_offset [ 48 + 32 + i ] = ( 4 * ( ( scan8 [ i ] - scan8 [ 0 ] ) & 7 ) < < pixel_shift ) + 8 * pic - > f - > linesize [ 1 ] * ( ( scan8 [ i ] - scan8 [ 0 ] ) > > 3 ) ;
2014-03-19 18:52:47 +03:00
}
/* We mark the current picture as non-reference after allocating it, so
* that if we break out due to an error it can be released automatically
2014-08-10 18:25:12 +03:00
* in the next ff_mpv_frame_start ( ) .
2014-03-19 18:52:47 +03:00
*/
h - > cur_pic_ptr - > reference = 0 ;
h - > cur_pic_ptr - > field_poc [ 0 ] = h - > cur_pic_ptr - > field_poc [ 1 ] = INT_MAX ;
h - > next_output_pic = NULL ;
2016-04-13 13:52:36 +02:00
h - > postpone_filter = 0 ;
2016-05-17 15:07:23 +02:00
h - > mb_aff_frame = h - > ps . sps - > mb_aff & & ( h - > picture_structure = = PICT_FRAME ) ;
2014-03-19 18:52:47 +03:00
assert ( h - > cur_pic_ptr - > long_ref = = 0 ) ;
return 0 ;
}
2015-01-28 14:24:32 +02:00
static av_always_inline void backup_mb_border ( const H264Context * h , H264SliceContext * sl ,
2015-01-17 23:28:46 +02:00
uint8_t * src_y ,
2014-03-19 18:52:47 +03:00
uint8_t * src_cb , uint8_t * src_cr ,
int linesize , int uvlinesize ,
int simple )
{
uint8_t * top_border ;
int top_idx = 1 ;
const int pixel_shift = h - > pixel_shift ;
int chroma444 = CHROMA444 ( h ) ;
int chroma422 = CHROMA422 ( h ) ;
src_y - = linesize ;
src_cb - = uvlinesize ;
src_cr - = uvlinesize ;
if ( ! simple & & FRAME_MBAFF ( h ) ) {
2015-01-17 23:28:46 +02:00
if ( sl - > mb_y & 1 ) {
2015-01-17 23:28:46 +02:00
if ( ! MB_MBAFF ( sl ) ) {
2015-01-17 23:28:46 +02:00
top_border = sl - > top_borders [ 0 ] [ sl - > mb_x ] ;
2014-03-19 18:52:47 +03:00
AV_COPY128 ( top_border , src_y + 15 * linesize ) ;
if ( pixel_shift )
AV_COPY128 ( top_border + 16 , src_y + 15 * linesize + 16 ) ;
2015-06-29 21:59:37 +02:00
if ( simple | | ! CONFIG_GRAY | | ! ( h - > flags & AV_CODEC_FLAG_GRAY ) ) {
2014-03-19 18:52:47 +03:00
if ( chroma444 ) {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 15 * uvlinesize ) ;
AV_COPY128 ( top_border + 48 , src_cb + 15 * uvlinesize + 16 ) ;
AV_COPY128 ( top_border + 64 , src_cr + 15 * uvlinesize ) ;
AV_COPY128 ( top_border + 80 , src_cr + 15 * uvlinesize + 16 ) ;
} else {
AV_COPY128 ( top_border + 16 , src_cb + 15 * uvlinesize ) ;
AV_COPY128 ( top_border + 32 , src_cr + 15 * uvlinesize ) ;
}
} else if ( chroma422 ) {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 15 * uvlinesize ) ;
AV_COPY128 ( top_border + 48 , src_cr + 15 * uvlinesize ) ;
} else {
AV_COPY64 ( top_border + 16 , src_cb + 15 * uvlinesize ) ;
AV_COPY64 ( top_border + 24 , src_cr + 15 * uvlinesize ) ;
}
} else {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 7 * uvlinesize ) ;
AV_COPY128 ( top_border + 48 , src_cr + 7 * uvlinesize ) ;
} else {
AV_COPY64 ( top_border + 16 , src_cb + 7 * uvlinesize ) ;
AV_COPY64 ( top_border + 24 , src_cr + 7 * uvlinesize ) ;
}
}
}
}
2015-01-17 23:28:46 +02:00
} else if ( MB_MBAFF ( sl ) ) {
2014-03-19 18:52:47 +03:00
top_idx = 0 ;
} else
return ;
}
2015-01-17 23:28:46 +02:00
top_border = sl - > top_borders [ top_idx ] [ sl - > mb_x ] ;
2014-03-19 18:52:47 +03:00
/* There are two lines saved, the line above the top macroblock
* of a pair , and the line above the bottom macroblock . */
AV_COPY128 ( top_border , src_y + 16 * linesize ) ;
if ( pixel_shift )
AV_COPY128 ( top_border + 16 , src_y + 16 * linesize + 16 ) ;
2015-06-29 21:59:37 +02:00
if ( simple | | ! CONFIG_GRAY | | ! ( h - > flags & AV_CODEC_FLAG_GRAY ) ) {
2014-03-19 18:52:47 +03:00
if ( chroma444 ) {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 16 * linesize ) ;
AV_COPY128 ( top_border + 48 , src_cb + 16 * linesize + 16 ) ;
AV_COPY128 ( top_border + 64 , src_cr + 16 * linesize ) ;
AV_COPY128 ( top_border + 80 , src_cr + 16 * linesize + 16 ) ;
} else {
AV_COPY128 ( top_border + 16 , src_cb + 16 * linesize ) ;
AV_COPY128 ( top_border + 32 , src_cr + 16 * linesize ) ;
}
} else if ( chroma422 ) {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 16 * uvlinesize ) ;
AV_COPY128 ( top_border + 48 , src_cr + 16 * uvlinesize ) ;
} else {
AV_COPY64 ( top_border + 16 , src_cb + 16 * uvlinesize ) ;
AV_COPY64 ( top_border + 24 , src_cr + 16 * uvlinesize ) ;
}
} else {
if ( pixel_shift ) {
AV_COPY128 ( top_border + 32 , src_cb + 8 * uvlinesize ) ;
AV_COPY128 ( top_border + 48 , src_cr + 8 * uvlinesize ) ;
} else {
AV_COPY64 ( top_border + 16 , src_cb + 8 * uvlinesize ) ;
AV_COPY64 ( top_border + 24 , src_cr + 8 * uvlinesize ) ;
}
}
}
}
/**
* Initialize implicit_weight table .
* @ param field 0 / 1 initialize the weight for interlaced MBAFF
* - 1 initializes the rest
*/
2015-01-28 14:24:32 +02:00
static void implicit_weight_table ( const H264Context * h , H264SliceContext * sl , int field )
2014-03-19 18:52:47 +03:00
{
int ref0 , ref1 , i , cur_poc , ref_start , ref_count0 , ref_count1 ;
for ( i = 0 ; i < 2 ; i + + ) {
2016-03-21 17:14:31 +02:00
sl - > pwt . luma_weight_flag [ i ] = 0 ;
sl - > pwt . chroma_weight_flag [ i ] = 0 ;
2014-03-19 18:52:47 +03:00
}
if ( field < 0 ) {
if ( h - > picture_structure = = PICT_FRAME ) {
cur_poc = h - > cur_pic_ptr - > poc ;
} else {
cur_poc = h - > cur_pic_ptr - > field_poc [ h - > picture_structure - 1 ] ;
}
2015-01-17 23:28:46 +02:00
if ( sl - > ref_count [ 0 ] = = 1 & & sl - > ref_count [ 1 ] = = 1 & & ! FRAME_MBAFF ( h ) & &
2016-01-05 02:06:18 +02:00
sl - > ref_list [ 0 ] [ 0 ] . poc + ( int64_t ) sl - > ref_list [ 1 ] [ 0 ] . poc = = 2 * cur_poc ) {
2016-03-21 17:14:31 +02:00
sl - > pwt . use_weight = 0 ;
sl - > pwt . use_weight_chroma = 0 ;
2014-03-19 18:52:47 +03:00
return ;
}
ref_start = 0 ;
2015-01-17 23:28:46 +02:00
ref_count0 = sl - > ref_count [ 0 ] ;
ref_count1 = sl - > ref_count [ 1 ] ;
2014-03-19 18:52:47 +03:00
} else {
cur_poc = h - > cur_pic_ptr - > field_poc [ field ] ;
ref_start = 16 ;
2015-01-17 23:28:46 +02:00
ref_count0 = 16 + 2 * sl - > ref_count [ 0 ] ;
ref_count1 = 16 + 2 * sl - > ref_count [ 1 ] ;
2014-03-19 18:52:47 +03:00
}
2016-03-21 17:14:31 +02:00
sl - > pwt . use_weight = 2 ;
sl - > pwt . use_weight_chroma = 2 ;
sl - > pwt . luma_log2_weight_denom = 5 ;
sl - > pwt . chroma_log2_weight_denom = 5 ;
2014-03-19 18:52:47 +03:00
for ( ref0 = ref_start ; ref0 < ref_count0 ; ref0 + + ) {
2016-01-05 02:06:18 +02:00
int64_t poc0 = sl - > ref_list [ 0 ] [ ref0 ] . poc ;
2014-03-19 18:52:47 +03:00
for ( ref1 = ref_start ; ref1 < ref_count1 ; ref1 + + ) {
int w = 32 ;
2015-01-29 09:42:14 +02:00
if ( ! sl - > ref_list [ 0 ] [ ref0 ] . parent - > long_ref & & ! sl - > ref_list [ 1 ] [ ref1 ] . parent - > long_ref ) {
2015-01-17 23:28:46 +02:00
int poc1 = sl - > ref_list [ 1 ] [ ref1 ] . poc ;
2015-02-20 02:35:35 +02:00
int td = av_clip_int8 ( poc1 - poc0 ) ;
2014-03-19 18:52:47 +03:00
if ( td ) {
2015-02-20 02:35:35 +02:00
int tb = av_clip_int8 ( cur_poc - poc0 ) ;
2014-03-19 18:52:47 +03:00
int tx = ( 16384 + ( FFABS ( td ) > > 1 ) ) / td ;
int dist_scale_factor = ( tb * tx + 32 ) > > 8 ;
if ( dist_scale_factor > = - 64 & & dist_scale_factor < = 128 )
w = 64 - dist_scale_factor ;
}
}
if ( field < 0 ) {
2016-03-21 17:14:31 +02:00
sl - > pwt . implicit_weight [ ref0 ] [ ref1 ] [ 0 ] =
sl - > pwt . implicit_weight [ ref0 ] [ ref1 ] [ 1 ] = w ;
2014-03-19 18:52:47 +03:00
} else {
2016-03-21 17:14:31 +02:00
sl - > pwt . implicit_weight [ ref0 ] [ ref1 ] [ field ] = w ;
2014-03-19 18:52:47 +03:00
}
}
}
}
/**
* initialize scan tables
*/
static void init_scan_tables ( H264Context * h )
{
int i ;
for ( i = 0 ; i < 16 ; i + + ) {
2014-05-25 04:33:46 +03:00
# define TRANSPOSE(x) ((x) >> 2) | (((x) << 2) & 0xF)
2016-03-24 12:16:53 +02:00
h - > zigzag_scan [ i ] = TRANSPOSE ( ff_zigzag_scan [ i ] ) ;
2014-03-19 18:52:47 +03:00
h - > field_scan [ i ] = TRANSPOSE ( field_scan [ i ] ) ;
# undef TRANSPOSE
}
for ( i = 0 ; i < 64 ; i + + ) {
2014-05-25 04:33:46 +03:00
# define TRANSPOSE(x) ((x) >> 3) | (((x) & 7) << 3)
2014-03-19 18:52:47 +03:00
h - > zigzag_scan8x8 [ i ] = TRANSPOSE ( ff_zigzag_direct [ i ] ) ;
h - > zigzag_scan8x8_cavlc [ i ] = TRANSPOSE ( zigzag_scan8x8_cavlc [ i ] ) ;
h - > field_scan8x8 [ i ] = TRANSPOSE ( field_scan8x8 [ i ] ) ;
h - > field_scan8x8_cavlc [ i ] = TRANSPOSE ( field_scan8x8_cavlc [ i ] ) ;
# undef TRANSPOSE
}
2016-03-22 14:31:21 +02:00
if ( h - > ps . sps - > transform_bypass ) { // FIXME same ugly
2016-04-24 12:47:15 +02:00
memcpy ( h - > zigzag_scan_q0 , ff_zigzag_scan , sizeof ( h - > zigzag_scan_q0 ) ) ;
2014-03-24 03:24:55 +03:00
memcpy ( h - > zigzag_scan8x8_q0 , ff_zigzag_direct , sizeof ( h - > zigzag_scan8x8_q0 ) ) ;
memcpy ( h - > zigzag_scan8x8_cavlc_q0 , zigzag_scan8x8_cavlc , sizeof ( h - > zigzag_scan8x8_cavlc_q0 ) ) ;
memcpy ( h - > field_scan_q0 , field_scan , sizeof ( h - > field_scan_q0 ) ) ;
memcpy ( h - > field_scan8x8_q0 , field_scan8x8 , sizeof ( h - > field_scan8x8_q0 ) ) ;
memcpy ( h - > field_scan8x8_cavlc_q0 , field_scan8x8_cavlc , sizeof ( h - > field_scan8x8_cavlc_q0 ) ) ;
2014-03-19 18:52:47 +03:00
} else {
2014-03-24 03:24:55 +03:00
memcpy ( h - > zigzag_scan_q0 , h - > zigzag_scan , sizeof ( h - > zigzag_scan_q0 ) ) ;
memcpy ( h - > zigzag_scan8x8_q0 , h - > zigzag_scan8x8 , sizeof ( h - > zigzag_scan8x8_q0 ) ) ;
memcpy ( h - > zigzag_scan8x8_cavlc_q0 , h - > zigzag_scan8x8_cavlc , sizeof ( h - > zigzag_scan8x8_cavlc_q0 ) ) ;
memcpy ( h - > field_scan_q0 , h - > field_scan , sizeof ( h - > field_scan_q0 ) ) ;
memcpy ( h - > field_scan8x8_q0 , h - > field_scan8x8 , sizeof ( h - > field_scan8x8_q0 ) ) ;
memcpy ( h - > field_scan8x8_cavlc_q0 , h - > field_scan8x8_cavlc , sizeof ( h - > field_scan8x8_cavlc_q0 ) ) ;
2014-03-19 18:52:47 +03:00
}
}
2014-03-24 03:24:55 +03:00
static enum AVPixelFormat get_pixel_format ( H264Context * h , int force_callback )
2014-03-19 18:52:47 +03:00
{
2014-12-19 19:15:06 +02:00
# define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
2015-05-26 05:08:32 +02:00
CONFIG_H264_D3D11VA_HWACCEL + \
2014-12-19 19:15:06 +02:00
CONFIG_H264_VAAPI_HWACCEL + \
( CONFIG_H264_VDA_HWACCEL * 2 ) + \
2015-07-11 13:23:21 +02:00
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
2014-12-19 19:15:06 +02:00
CONFIG_H264_VDPAU_HWACCEL )
enum AVPixelFormat pix_fmts [ HWACCEL_MAX + 2 ] , * fmt = pix_fmts ;
2014-09-25 11:59:57 +03:00
const enum AVPixelFormat * choices = pix_fmts ;
2014-09-27 04:16:58 +03:00
int i ;
2014-09-25 11:59:57 +03:00
2016-03-22 14:31:21 +02:00
switch ( h - > ps . sps - > bit_depth_luma ) {
2014-03-19 18:52:47 +03:00
case 9 :
if ( CHROMA444 ( h ) ) {
if ( h - > avctx - > colorspace = = AVCOL_SPC_RGB ) {
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_GBRP9 ;
2014-03-19 18:52:47 +03:00
} else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV444P9 ;
2014-03-19 18:52:47 +03:00
} else if ( CHROMA422 ( h ) )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV422P9 ;
2014-03-19 18:52:47 +03:00
else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV420P9 ;
2014-03-19 18:52:47 +03:00
break ;
case 10 :
if ( CHROMA444 ( h ) ) {
if ( h - > avctx - > colorspace = = AVCOL_SPC_RGB ) {
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_GBRP10 ;
2014-03-19 18:52:47 +03:00
} else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV444P10 ;
2014-03-19 18:52:47 +03:00
} else if ( CHROMA422 ( h ) )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV422P10 ;
2014-03-19 18:52:47 +03:00
else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV420P10 ;
2014-03-19 18:52:47 +03:00
break ;
2014-03-24 03:24:55 +03:00
case 12 :
2014-03-19 18:52:47 +03:00
if ( CHROMA444 ( h ) ) {
if ( h - > avctx - > colorspace = = AVCOL_SPC_RGB ) {
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_GBRP12 ;
2014-03-19 18:52:47 +03:00
} else
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV444P12 ;
2014-03-24 03:24:55 +03:00
} else if ( CHROMA422 ( h ) )
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV422P12 ;
2014-03-24 03:24:55 +03:00
else
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV420P12 ;
2014-03-24 03:24:55 +03:00
break ;
case 14 :
if ( CHROMA444 ( h ) ) {
if ( h - > avctx - > colorspace = = AVCOL_SPC_RGB ) {
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_GBRP14 ;
2014-03-24 03:24:55 +03:00
} else
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV444P14 ;
2014-03-24 03:24:55 +03:00
} else if ( CHROMA422 ( h ) )
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV422P14 ;
2014-03-24 03:24:55 +03:00
else
2014-12-27 13:15:34 +02:00
* fmt + + = AV_PIX_FMT_YUV420P14 ;
2014-03-24 03:24:55 +03:00
break ;
case 8 :
2014-12-19 19:15:10 +02:00
# if CONFIG_H264_VDPAU_HWACCEL
* fmt + + = AV_PIX_FMT_VDPAU ;
# endif
2014-03-24 03:24:55 +03:00
if ( CHROMA444 ( h ) ) {
2014-09-25 11:59:57 +03:00
if ( h - > avctx - > colorspace = = AVCOL_SPC_RGB )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_GBRP ;
2014-09-25 11:59:57 +03:00
else if ( h - > avctx - > color_range = = AVCOL_RANGE_JPEG )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUVJ444P ;
2014-09-25 11:59:57 +03:00
else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV444P ;
2014-03-19 18:52:47 +03:00
} else if ( CHROMA422 ( h ) ) {
2014-09-25 11:59:57 +03:00
if ( h - > avctx - > color_range = = AVCOL_RANGE_JPEG )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUVJ422P ;
2014-09-25 11:59:57 +03:00
else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV422P ;
2014-03-19 18:52:47 +03:00
} else {
2014-12-19 19:15:06 +02:00
# if CONFIG_H264_DXVA2_HWACCEL
* fmt + + = AV_PIX_FMT_DXVA2_VLD ;
# endif
2015-05-11 10:52:47 +02:00
# if CONFIG_H264_D3D11VA_HWACCEL
* fmt + + = AV_PIX_FMT_D3D11VA_VLD ;
# endif
2014-12-19 19:15:06 +02:00
# if CONFIG_H264_VAAPI_HWACCEL
2015-07-28 10:16:59 +02:00
* fmt + + = AV_PIX_FMT_VAAPI ;
2014-12-19 19:15:06 +02:00
# endif
# if CONFIG_H264_VDA_HWACCEL
* fmt + + = AV_PIX_FMT_VDA_VLD ;
* fmt + + = AV_PIX_FMT_VDA ;
2015-07-11 13:23:21 +02:00
# endif
# if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
* fmt + + = AV_PIX_FMT_VIDEOTOOLBOX ;
2014-12-19 19:15:06 +02:00
# endif
2014-09-25 11:59:57 +03:00
if ( h - > avctx - > codec - > pix_fmts )
choices = h - > avctx - > codec - > pix_fmts ;
else if ( h - > avctx - > color_range = = AVCOL_RANGE_JPEG )
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUVJ420P ;
2014-09-25 11:59:57 +03:00
else
2014-12-19 19:15:06 +02:00
* fmt + + = AV_PIX_FMT_YUV420P ;
2014-03-19 18:52:47 +03:00
}
break ;
default :
av_log ( h - > avctx , AV_LOG_ERROR ,
2016-03-22 14:31:21 +02:00
" Unsupported bit depth %d \n " , h - > ps . sps - > bit_depth_luma ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
2014-09-25 11:59:57 +03:00
2014-12-19 19:15:06 +02:00
* fmt = AV_PIX_FMT_NONE ;
2014-09-27 04:16:58 +03:00
for ( i = 0 ; choices [ i ] ! = AV_PIX_FMT_NONE ; i + + )
if ( choices [ i ] = = h - > avctx - > pix_fmt & & ! force_callback )
return choices [ i ] ;
return ff_thread_get_format ( h - > avctx , choices ) ;
2014-03-19 18:52:47 +03:00
}
/* export coded and cropped frame dimensions to AVCodecContext */
static int init_dimensions ( H264Context * h )
{
2016-06-21 14:17:13 +02:00
const SPS * sps = ( const SPS * ) h - > ps . sps ;
2016-03-22 14:31:21 +02:00
int width = h - > width - ( sps - > crop_right + sps - > crop_left ) ;
int height = h - > height - ( sps - > crop_top + sps - > crop_bottom ) ;
2016-06-12 13:24:27 +02:00
av_assert0 ( sps - > crop_right + sps - > crop_left < ( unsigned ) h - > width ) ;
av_assert0 ( sps - > crop_top + sps - > crop_bottom < ( unsigned ) h - > height ) ;
2014-03-19 18:52:47 +03:00
/* handle container cropping */
2015-03-08 06:06:32 +02:00
if ( FFALIGN ( h - > avctx - > width , 16 ) = = FFALIGN ( width , 16 ) & &
2015-07-08 17:49:00 +02:00
FFALIGN ( h - > avctx - > height , 16 ) = = FFALIGN ( height , 16 ) & &
h - > avctx - > width < = width & &
h - > avctx - > height < = height
) {
2014-03-19 18:52:47 +03:00
width = h - > avctx - > width ;
height = h - > avctx - > height ;
}
h - > avctx - > coded_width = h - > width ;
h - > avctx - > coded_height = h - > height ;
h - > avctx - > width = width ;
h - > avctx - > height = height ;
return 0 ;
}
2015-04-12 19:36:49 +02:00
static int h264_slice_header_init ( H264Context * h )
2014-03-19 18:52:47 +03:00
{
2016-03-22 14:31:21 +02:00
const SPS * sps = h - > ps . sps ;
2014-03-19 18:52:47 +03:00
int i , ret ;
2016-03-22 14:31:21 +02:00
ff_set_sar ( h - > avctx , sps - > sar ) ;
2014-03-19 18:52:47 +03:00
av_pix_fmt_get_chroma_sub_sample ( h - > avctx - > pix_fmt ,
& h - > chroma_x_shift , & h - > chroma_y_shift ) ;
2016-03-22 14:31:21 +02:00
if ( sps - > timing_info_present_flag ) {
int64_t den = sps - > time_scale ;
2016-03-22 14:31:21 +02:00
if ( h - > sei . unregistered . x264_build < 44U )
2014-03-19 18:52:47 +03:00
den * = 2 ;
2014-04-04 13:47:44 +03:00
av_reduce ( & h - > avctx - > framerate . den , & h - > avctx - > framerate . num ,
2016-06-12 13:24:27 +02:00
sps - > num_units_in_tick * h - > avctx - > ticks_per_frame , den , 1 < < 30 ) ;
2014-03-19 18:52:47 +03:00
}
2015-04-12 19:36:49 +02:00
ff_h264_free_tables ( h ) ;
2014-03-19 18:52:47 +03:00
h - > first_field = 0 ;
h - > prev_interlaced_frame = 1 ;
init_scan_tables ( h ) ;
ret = ff_h264_alloc_tables ( h ) ;
if ( ret < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR , " Could not allocate memory \n " ) ;
2014-08-21 17:33:03 +03:00
goto fail ;
2014-03-19 18:52:47 +03:00
}
2015-08-17 01:35:59 +02:00
# if FF_API_CAP_VDPAU
2015-04-29 13:01:15 +02:00
if ( h - > avctx - > codec & &
2015-07-27 22:21:19 +02:00
h - > avctx - > codec - > capabilities & AV_CODEC_CAP_HWACCEL_VDPAU & &
2016-06-12 13:24:27 +02:00
( sps - > bit_depth_luma ! = 8 | | sps - > chroma_format_idc > 1 ) ) {
2015-04-29 13:01:15 +02:00
av_log ( h - > avctx , AV_LOG_ERROR ,
" VDPAU decoding does not support video colorspace. \n " ) ;
ret = AVERROR_INVALIDDATA ;
goto fail ;
2014-03-19 18:52:47 +03:00
}
2015-08-17 01:35:59 +02:00
# endif
2014-03-19 18:52:47 +03:00
2016-06-12 13:24:27 +02:00
if ( sps - > bit_depth_luma < 8 | | sps - > bit_depth_luma > 14 | |
sps - > bit_depth_luma = = 11 | | sps - > bit_depth_luma = = 13
2015-04-29 13:01:15 +02:00
) {
2015-04-06 20:33:58 +02:00
av_log ( h - > avctx , AV_LOG_ERROR , " Unsupported bit depth %d \n " ,
2016-03-22 14:31:21 +02:00
sps - > bit_depth_luma ) ;
2015-04-29 13:01:15 +02:00
ret = AVERROR_INVALIDDATA ;
goto fail ;
2015-04-06 20:33:58 +02:00
}
2015-04-29 13:01:15 +02:00
h - > cur_bit_depth_luma =
2016-03-22 14:31:21 +02:00
h - > avctx - > bits_per_raw_sample = sps - > bit_depth_luma ;
2016-06-12 13:24:27 +02:00
h - > cur_chroma_format_idc = sps - > chroma_format_idc ;
2016-03-22 14:31:21 +02:00
h - > pixel_shift = sps - > bit_depth_luma > 8 ;
h - > chroma_format_idc = sps - > chroma_format_idc ;
h - > bit_depth_luma = sps - > bit_depth_luma ;
2015-04-06 20:33:58 +02:00
2016-03-22 14:31:21 +02:00
ff_h264dsp_init ( & h - > h264dsp , sps - > bit_depth_luma ,
sps - > chroma_format_idc ) ;
ff_h264chroma_init ( & h - > h264chroma , sps - > bit_depth_chroma ) ;
ff_h264qpel_init ( & h - > h264qpel , sps - > bit_depth_luma ) ;
ff_h264_pred_init ( & h - > hpc , h - > avctx - > codec_id , sps - > bit_depth_luma ,
sps - > chroma_format_idc ) ;
ff_videodsp_init ( & h - > vdsp , sps - > bit_depth_luma ) ;
2015-04-06 20:33:58 +02:00
2014-03-19 18:52:47 +03:00
if ( ! HAVE_THREADS | | ! ( h - > avctx - > active_thread_type & FF_THREAD_SLICE ) ) {
2015-01-17 23:28:46 +02:00
ret = ff_h264_slice_context_init ( h , & h - > slice_ctx [ 0 ] ) ;
2014-03-19 18:52:47 +03:00
if ( ret < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR , " context_init() failed. \n " ) ;
2014-08-21 17:33:03 +03:00
goto fail ;
2014-03-19 18:52:47 +03:00
}
} else {
2016-04-13 17:28:26 +02:00
for ( i = 0 ; i < h - > nb_slice_ctx ; i + + ) {
2015-01-28 20:28:18 +02:00
H264SliceContext * sl = & h - > slice_ctx [ i ] ;
2014-03-19 18:52:47 +03:00
2015-01-28 20:28:18 +02:00
sl - > h264 = h ;
sl - > intra4x4_pred_mode = h - > intra4x4_pred_mode + i * 8 * 2 * h - > mb_stride ;
sl - > mvd_table [ 0 ] = h - > mvd_table [ 0 ] + i * 8 * 2 * h - > mb_stride ;
sl - > mvd_table [ 1 ] = h - > mvd_table [ 1 ] + i * 8 * 2 * h - > mb_stride ;
2014-03-19 18:52:47 +03:00
2015-01-28 20:28:18 +02:00
if ( ( ret = ff_h264_slice_context_init ( h , sl ) ) < 0 ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR , " context_init() failed. \n " ) ;
2014-08-21 17:33:03 +03:00
goto fail ;
2014-03-19 18:52:47 +03:00
}
2015-01-28 20:28:18 +02:00
}
2014-03-19 18:52:47 +03:00
}
h - > context_initialized = 1 ;
return 0 ;
2014-08-21 17:33:03 +03:00
fail :
2015-04-29 13:24:18 +02:00
ff_h264_free_tables ( h ) ;
2014-08-21 17:33:03 +03:00
h - > context_initialized = 0 ;
return ret ;
2014-03-19 18:52:47 +03:00
}
2015-10-15 20:19:55 +02:00
static enum AVPixelFormat non_j_pixfmt ( enum AVPixelFormat a )
{
switch ( a ) {
case AV_PIX_FMT_YUVJ420P : return AV_PIX_FMT_YUV420P ;
case AV_PIX_FMT_YUVJ422P : return AV_PIX_FMT_YUV422P ;
case AV_PIX_FMT_YUVJ444P : return AV_PIX_FMT_YUV444P ;
default :
return a ;
}
}
2016-07-09 13:50:16 +02:00
static int h264_init_ps ( H264Context * h , const H264SliceContext * sl , int first_slice )
2016-05-12 14:37:35 +02:00
{
const SPS * sps ;
2016-07-09 13:50:16 +02:00
int needs_reinit = 0 , must_reinit , ret ;
if ( first_slice ) {
av_buffer_unref ( & h - > ps . pps_ref ) ;
h - > ps . pps = NULL ;
h - > ps . pps_ref = av_buffer_ref ( h - > ps . pps_list [ sl - > pps_id ] ) ;
if ( ! h - > ps . pps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . pps = ( const PPS * ) h - > ps . pps_ref - > data ;
}
2016-05-12 14:37:35 +02:00
if ( h - > ps . sps ! = ( const SPS * ) h - > ps . sps_list [ h - > ps . pps - > sps_id ] - > data ) {
2016-07-09 13:50:16 +02:00
av_buffer_unref ( & h - > ps . sps_ref ) ;
h - > ps . sps = NULL ;
h - > ps . sps_ref = av_buffer_ref ( h - > ps . sps_list [ h - > ps . pps - > sps_id ] ) ;
if ( ! h - > ps . sps_ref )
return AVERROR ( ENOMEM ) ;
h - > ps . sps = ( const SPS * ) h - > ps . sps_ref - > data ;
if ( h - > mb_width ! = h - > ps . sps - > mb_width | |
h - > mb_height ! = h - > ps . sps - > mb_height * ( 2 - h - > ps . sps - > frame_mbs_only_flag ) | |
h - > cur_bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > cur_chroma_format_idc ! = h - > ps . sps - > chroma_format_idc
)
needs_reinit = 1 ;
2016-05-12 14:37:35 +02:00
if ( h - > bit_depth_luma ! = h - > ps . sps - > bit_depth_luma | |
h - > chroma_format_idc ! = h - > ps . sps - > chroma_format_idc )
needs_reinit = 1 ;
}
sps = h - > ps . sps ;
2016-07-09 13:50:16 +02:00
must_reinit = ( h - > context_initialized & &
( 16 * sps - > mb_width ! = h - > avctx - > coded_width
| | 16 * sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ! = h - > avctx - > coded_height
| | h - > cur_bit_depth_luma ! = sps - > bit_depth_luma
| | h - > cur_chroma_format_idc ! = sps - > chroma_format_idc
| | h - > mb_width ! = sps - > mb_width
| | h - > mb_height ! = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag )
) ) ;
if ( h - > avctx - > pix_fmt = = AV_PIX_FMT_NONE
| | ( non_j_pixfmt ( h - > avctx - > pix_fmt ) ! = non_j_pixfmt ( get_pixel_format ( h , 0 ) ) ) )
must_reinit = 1 ;
if ( first_slice & & av_cmp_q ( sps - > sar , h - > avctx - > sample_aspect_ratio ) )
must_reinit = 1 ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
if ( ! h - > setup_finished ) {
h - > avctx - > profile = ff_h264_get_profile ( sps ) ;
h - > avctx - > level = sps - > level_idc ;
h - > avctx - > refs = sps - > ref_frame_count ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
h - > mb_width = sps - > mb_width ;
h - > mb_height = sps - > mb_height * ( 2 - sps - > frame_mbs_only_flag ) ;
h - > mb_num = h - > mb_width * h - > mb_height ;
h - > mb_stride = h - > mb_width + 1 ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
h - > b_stride = h - > mb_width * 4 ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
h - > chroma_y_shift = sps - > chroma_format_idc < = 1 ; // 400 uses yuv420p
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
h - > width = 16 * h - > mb_width ;
h - > height = 16 * h - > mb_height ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
ret = init_dimensions ( h ) ;
if ( ret < 0 )
return ret ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
if ( sps - > video_signal_type_present_flag ) {
h - > avctx - > color_range = sps - > full_range > 0 ? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG ;
if ( sps - > colour_description_present_flag ) {
if ( h - > avctx - > colorspace ! = sps - > colorspace )
needs_reinit = 1 ;
h - > avctx - > color_primaries = sps - > color_primaries ;
h - > avctx - > color_trc = sps - > color_trc ;
h - > avctx - > colorspace = sps - > colorspace ;
}
2016-05-12 14:37:35 +02:00
}
}
2016-07-09 13:50:16 +02:00
if ( ! h - > context_initialized | | must_reinit | | needs_reinit ) {
int flush_changes = h - > context_initialized ;
2016-05-12 14:37:35 +02:00
h - > context_initialized = 0 ;
if ( sl ! = h - > slice_ctx ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" changing width %d -> %d / height %d -> %d on "
" slice %d \n " ,
h - > width , h - > avctx - > coded_width ,
h - > height , h - > avctx - > coded_height ,
h - > current_slice + 1 ) ;
return AVERROR_INVALIDDATA ;
}
2016-07-09 13:50:16 +02:00
av_assert1 ( first_slice ) ;
if ( flush_changes )
ff_h264_flush_change ( h ) ;
2016-05-12 14:37:35 +02:00
2016-07-09 13:50:16 +02:00
if ( ( ret = get_pixel_format ( h , 1 ) ) < 0 )
2016-05-12 14:37:35 +02:00
return ret ;
h - > avctx - > pix_fmt = ret ;
av_log ( h - > avctx , AV_LOG_VERBOSE , " Reinit context to %dx%d, "
2016-07-09 13:50:16 +02:00
" pix_fmt: %s \n " , h - > width , h - > height , av_get_pix_fmt_name ( h - > avctx - > pix_fmt ) ) ;
2016-05-12 14:37:35 +02:00
if ( ( ret = h264_slice_header_init ( h ) ) < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" h264_slice_header_init() failed \n " ) ;
return ret ;
}
}
return 0 ;
}
2016-05-18 07:27:32 +02:00
static int h264_export_frame_props ( H264Context * h )
{
const SPS * sps = h - > ps . sps ;
H264Picture * cur = h - > cur_pic_ptr ;
cur - > f - > interlaced_frame = 0 ;
cur - > f - > repeat_pict = 0 ;
/* Signal interlacing information externally. */
/* Prioritize picture timing SEI information over used
* decoding process if it exists . */
if ( sps - > pic_struct_present_flag ) {
H264SEIPictureTiming * pt = & h - > sei . picture_timing ;
switch ( pt - > pic_struct ) {
case SEI_PIC_STRUCT_FRAME :
break ;
case SEI_PIC_STRUCT_TOP_FIELD :
case SEI_PIC_STRUCT_BOTTOM_FIELD :
cur - > f - > interlaced_frame = 1 ;
break ;
case SEI_PIC_STRUCT_TOP_BOTTOM :
case SEI_PIC_STRUCT_BOTTOM_TOP :
if ( FIELD_OR_MBAFF_PICTURE ( h ) )
cur - > f - > interlaced_frame = 1 ;
else
// try to flag soft telecine progressive
cur - > f - > interlaced_frame = h - > prev_interlaced_frame ;
break ;
case SEI_PIC_STRUCT_TOP_BOTTOM_TOP :
case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM :
/* Signal the possibility of telecined film externally
* ( pic_struct 5 , 6 ) . From these hints , let the applications
* decide if they apply deinterlacing . */
cur - > f - > repeat_pict = 1 ;
break ;
case SEI_PIC_STRUCT_FRAME_DOUBLING :
cur - > f - > repeat_pict = 2 ;
break ;
case SEI_PIC_STRUCT_FRAME_TRIPLING :
cur - > f - > repeat_pict = 4 ;
break ;
}
if ( ( pt - > ct_type & 3 ) & &
pt - > pic_struct < = SEI_PIC_STRUCT_BOTTOM_TOP )
cur - > f - > interlaced_frame = ( pt - > ct_type & ( 1 < < 1 ) ) ! = 0 ;
} else {
/* Derive interlacing flag from used decoding process. */
cur - > f - > interlaced_frame = FIELD_OR_MBAFF_PICTURE ( h ) ;
}
h - > prev_interlaced_frame = cur - > f - > interlaced_frame ;
if ( cur - > field_poc [ 0 ] ! = cur - > field_poc [ 1 ] ) {
/* Derive top_field_first from field pocs. */
cur - > f - > top_field_first = cur - > field_poc [ 0 ] < cur - > field_poc [ 1 ] ;
} else {
2016-07-29 10:39:57 +02:00
if ( sps - > pic_struct_present_flag ) {
2016-05-18 07:27:32 +02:00
/* Use picture timing SEI information. Even if it is a
* information of a past frame , better than nothing . */
if ( h - > sei . picture_timing . pic_struct = = SEI_PIC_STRUCT_TOP_BOTTOM | |
h - > sei . picture_timing . pic_struct = = SEI_PIC_STRUCT_TOP_BOTTOM_TOP )
cur - > f - > top_field_first = 1 ;
else
cur - > f - > top_field_first = 0 ;
2016-07-29 10:39:57 +02:00
} else if ( cur - > f - > interlaced_frame ) {
/* Default to top field first when pic_struct_present_flag
* is not set but interlaced frame detected */
cur - > f - > top_field_first = 1 ;
2016-05-18 07:27:32 +02:00
} else {
/* Most likely progressive */
cur - > f - > top_field_first = 0 ;
}
}
if ( h - > sei . frame_packing . present & &
2016-07-29 10:39:57 +02:00
h - > sei . frame_packing . frame_packing_arrangement_type < = 6 & &
2016-05-18 07:27:32 +02:00
h - > sei . frame_packing . content_interpretation_type > 0 & &
h - > sei . frame_packing . content_interpretation_type < 3 ) {
H264SEIFramePacking * fp = & h - > sei . frame_packing ;
AVStereo3D * stereo = av_stereo3d_create_side_data ( cur - > f ) ;
2016-07-29 10:39:57 +02:00
if ( stereo ) {
switch ( fp - > frame_packing_arrangement_type ) {
2016-05-18 07:27:32 +02:00
case 0 :
stereo - > type = AV_STEREO3D_CHECKERBOARD ;
break ;
case 1 :
stereo - > type = AV_STEREO3D_COLUMNS ;
break ;
case 2 :
stereo - > type = AV_STEREO3D_LINES ;
break ;
case 3 :
2016-07-29 10:39:57 +02:00
if ( fp - > quincunx_sampling_flag )
2016-05-18 07:27:32 +02:00
stereo - > type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX ;
else
stereo - > type = AV_STEREO3D_SIDEBYSIDE ;
break ;
case 4 :
stereo - > type = AV_STEREO3D_TOPBOTTOM ;
break ;
case 5 :
stereo - > type = AV_STEREO3D_FRAMESEQUENCE ;
break ;
case 6 :
stereo - > type = AV_STEREO3D_2D ;
break ;
}
if ( fp - > content_interpretation_type = = 2 )
stereo - > flags = AV_STEREO3D_FLAG_INVERT ;
2016-07-29 10:39:57 +02:00
}
2016-05-18 07:27:32 +02:00
}
if ( h - > sei . display_orientation . present & &
( h - > sei . display_orientation . anticlockwise_rotation | |
h - > sei . display_orientation . hflip | |
h - > sei . display_orientation . vflip ) ) {
H264SEIDisplayOrientation * o = & h - > sei . display_orientation ;
double angle = o - > anticlockwise_rotation * 360 / ( double ) ( 1 < < 16 ) ;
AVFrameSideData * rotation = av_frame_new_side_data ( cur - > f ,
AV_FRAME_DATA_DISPLAYMATRIX ,
sizeof ( int32_t ) * 9 ) ;
2016-07-29 10:39:57 +02:00
if ( rotation ) {
av_display_rotation_set ( ( int32_t * ) rotation - > data , angle ) ;
av_display_matrix_flip ( ( int32_t * ) rotation - > data ,
o - > hflip , o - > vflip ) ;
}
2016-05-18 07:27:32 +02:00
}
if ( h - > sei . afd . present ) {
AVFrameSideData * sd = av_frame_new_side_data ( cur - > f , AV_FRAME_DATA_AFD ,
sizeof ( uint8_t ) ) ;
2016-07-29 10:39:57 +02:00
if ( sd ) {
* sd - > data = h - > sei . afd . active_format_description ;
h - > sei . afd . present = 0 ;
}
2016-05-18 07:27:32 +02:00
}
if ( h - > sei . a53_caption . a53_caption ) {
H264SEIA53Caption * a53 = & h - > sei . a53_caption ;
AVFrameSideData * sd = av_frame_new_side_data ( cur - > f ,
AV_FRAME_DATA_A53_CC ,
a53 - > a53_caption_size ) ;
2016-07-29 10:39:57 +02:00
if ( sd )
memcpy ( sd - > data , a53 - > a53_caption , a53 - > a53_caption_size ) ;
2016-05-18 07:27:32 +02:00
av_freep ( & a53 - > a53_caption ) ;
a53 - > a53_caption_size = 0 ;
2016-07-29 10:39:57 +02:00
h - > avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
2016-05-18 07:27:32 +02:00
}
return 0 ;
}
2016-05-09 15:58:32 +02:00
/* This function is called right after decoding the slice header for a first
* slice in a field ( or a frame ) . It decides whether we are decoding a new frame
* or a second field in a pair and does the necessary setup .
*/
2016-05-16 09:34:44 +02:00
static int h264_field_start ( H264Context * h , const H264SliceContext * sl ,
2016-07-19 22:31:56 +02:00
const H2645NAL * nal , int first_slice )
2016-05-09 15:58:32 +02:00
{
2016-07-01 14:02:00 +02:00
int i ;
2016-05-12 14:37:35 +02:00
const SPS * sps ;
2016-05-09 15:58:32 +02:00
int last_pic_structure , last_pic_droppable , ret ;
2016-07-19 22:31:56 +02:00
ret = h264_init_ps ( h , sl , first_slice ) ;
if ( ret < 0 )
return ret ;
2016-05-12 14:37:35 +02:00
sps = h - > ps . sps ;
2016-05-09 15:58:32 +02:00
last_pic_droppable = h - > droppable ;
last_pic_structure = h - > picture_structure ;
2016-05-16 09:34:44 +02:00
h - > droppable = ( nal - > ref_idc = = 0 ) ;
2016-05-09 15:58:32 +02:00
h - > picture_structure = sl - > picture_structure ;
2016-05-17 15:35:50 +02:00
h - > poc . frame_num = sl - > frame_num ;
h - > poc . poc_lsb = sl - > poc_lsb ;
h - > poc . delta_poc_bottom = sl - > delta_poc_bottom ;
h - > poc . delta_poc [ 0 ] = sl - > delta_poc [ 0 ] ;
h - > poc . delta_poc [ 1 ] = sl - > delta_poc [ 1 ] ;
2016-05-09 15:58:32 +02:00
/* Shorten frame num gaps so we don't have to allocate reference
* frames just to throw them away */
if ( h - > poc . frame_num ! = h - > poc . prev_frame_num ) {
int unwrap_prev_frame_num = h - > poc . prev_frame_num ;
int max_frame_num = 1 < < sps - > log2_max_frame_num ;
if ( unwrap_prev_frame_num > h - > poc . frame_num )
unwrap_prev_frame_num - = max_frame_num ;
if ( ( h - > poc . frame_num - unwrap_prev_frame_num ) > sps - > ref_frame_count ) {
unwrap_prev_frame_num = ( h - > poc . frame_num - sps - > ref_frame_count ) - 1 ;
if ( unwrap_prev_frame_num < 0 )
unwrap_prev_frame_num + = max_frame_num ;
h - > poc . prev_frame_num = unwrap_prev_frame_num ;
}
}
/* See if we have a decoded first field looking for a pair...
* Here , we ' re using that to see if we should mark previously
* decode frames as " finished " .
* We have to do that before the " dummy " in - between frame allocation ,
2016-07-01 14:02:00 +02:00
* since that can modify h - > cur_pic_ptr . */
2016-05-09 15:58:32 +02:00
if ( h - > first_field ) {
2016-07-01 14:02:00 +02:00
av_assert0 ( h - > cur_pic_ptr ) ;
av_assert0 ( h - > cur_pic_ptr - > f - > buf [ 0 ] ) ;
2016-05-09 15:58:32 +02:00
assert ( h - > cur_pic_ptr - > reference ! = DELAYED_PIC_REF ) ;
2016-07-01 14:02:00 +02:00
/* Mark old field/frame as completed */
if ( h - > cur_pic_ptr - > tf . owner = = h - > avctx ) {
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX ,
last_pic_structure = = PICT_BOTTOM_FIELD ) ;
}
2016-05-09 15:58:32 +02:00
/* figure out if we have a complementary field pair */
if ( ! FIELD_PICTURE ( h ) | | h - > picture_structure = = last_pic_structure ) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such . */
2016-07-01 14:02:00 +02:00
if ( last_pic_structure ! = PICT_FRAME ) {
2016-05-09 15:58:32 +02:00
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX ,
last_pic_structure = = PICT_TOP_FIELD ) ;
}
} else {
if ( h - > cur_pic_ptr - > frame_num ! = h - > poc . frame_num ) {
/* This and previous field were reference, but had
* different frame_nums . Consider this field first in
* pair . Throw away previous field except for reference
* purposes . */
2016-07-01 14:02:00 +02:00
if ( last_pic_structure ! = PICT_FRAME ) {
2016-05-09 15:58:32 +02:00
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX ,
last_pic_structure = = PICT_TOP_FIELD ) ;
}
} else {
/* Second field in complementary pair */
if ( ! ( ( last_pic_structure = = PICT_TOP_FIELD & &
h - > picture_structure = = PICT_BOTTOM_FIELD ) | |
( last_pic_structure = = PICT_BOTTOM_FIELD & &
h - > picture_structure = = PICT_TOP_FIELD ) ) ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" Invalid field mode combination %d/%d \n " ,
last_pic_structure , h - > picture_structure ) ;
h - > picture_structure = last_pic_structure ;
h - > droppable = last_pic_droppable ;
return AVERROR_INVALIDDATA ;
} else if ( last_pic_droppable ! = h - > droppable ) {
avpriv_request_sample ( h - > avctx ,
" Found reference and non-reference fields in the same frame, which " ) ;
h - > picture_structure = last_pic_structure ;
h - > droppable = last_pic_droppable ;
return AVERROR_PATCHWELCOME ;
}
}
}
}
2016-07-01 14:02:00 +02:00
while ( h - > poc . frame_num ! = h - > poc . prev_frame_num & & ! h - > first_field & &
2016-05-09 15:58:32 +02:00
h - > poc . frame_num ! = ( h - > poc . prev_frame_num + 1 ) % ( 1 < < sps - > log2_max_frame_num ) ) {
H264Picture * prev = h - > short_ref_count ? h - > short_ref [ 0 ] : NULL ;
av_log ( h - > avctx , AV_LOG_DEBUG , " Frame num gap %d %d \n " ,
h - > poc . frame_num , h - > poc . prev_frame_num ) ;
2016-07-01 14:02:00 +02:00
if ( ! sps - > gaps_in_frame_num_allowed_flag )
for ( i = 0 ; i < FF_ARRAY_ELEMS ( h - > last_pocs ) ; i + + )
h - > last_pocs [ i ] = INT_MIN ;
ret = h264_frame_start ( h ) ;
2016-05-09 15:58:32 +02:00
if ( ret < 0 ) {
h - > first_field = 0 ;
return ret ;
}
h - > poc . prev_frame_num + + ;
h - > poc . prev_frame_num % = 1 < < sps - > log2_max_frame_num ;
h - > cur_pic_ptr - > frame_num = h - > poc . prev_frame_num ;
2016-07-01 14:02:00 +02:00
h - > cur_pic_ptr - > invalid_gap = ! sps - > gaps_in_frame_num_allowed_flag ;
2016-05-09 15:58:32 +02:00
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX , 0 ) ;
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX , 1 ) ;
h - > explicit_ref_marking = 0 ;
ret = ff_h264_execute_ref_pic_marking ( h ) ;
if ( ret < 0 & & ( h - > avctx - > err_recognition & AV_EF_EXPLODE ) )
return ret ;
/* Error concealment: If a ref is missing, copy the previous ref
* in its place .
* FIXME : Avoiding a memcpy would be nice , but ref handling makes
* many assumptions about there being no actual duplicates .
* FIXME : This does not copy padding for out - of - frame motion
* vectors . Given we are concealing a lost frame , this probably
* is not noticeable by comparison , but it should be fixed . */
if ( h - > short_ref_count ) {
if ( prev & &
h - > short_ref [ 0 ] - > f - > width = = prev - > f - > width & &
h - > short_ref [ 0 ] - > f - > height = = prev - > f - > height & &
h - > short_ref [ 0 ] - > f - > format = = prev - > f - > format ) {
av_image_copy ( h - > short_ref [ 0 ] - > f - > data ,
h - > short_ref [ 0 ] - > f - > linesize ,
( const uint8_t * * ) prev - > f - > data ,
prev - > f - > linesize ,
prev - > f - > format ,
2016-07-01 14:02:00 +02:00
prev - > f - > width ,
prev - > f - > height ) ;
2016-05-09 15:58:32 +02:00
h - > short_ref [ 0 ] - > poc = prev - > poc + 2 ;
}
h - > short_ref [ 0 ] - > frame_num = h - > poc . prev_frame_num ;
}
}
/* See if we have a decoded first field looking for a pair...
* We ' re using that to see whether to continue decoding in that
* frame , or to allocate a new one . */
if ( h - > first_field ) {
2016-07-01 14:02:00 +02:00
av_assert0 ( h - > cur_pic_ptr ) ;
av_assert0 ( h - > cur_pic_ptr - > f - > buf [ 0 ] ) ;
2016-05-09 15:58:32 +02:00
assert ( h - > cur_pic_ptr - > reference ! = DELAYED_PIC_REF ) ;
/* figure out if we have a complementary field pair */
if ( ! FIELD_PICTURE ( h ) | | h - > picture_structure = = last_pic_structure ) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such . */
2016-07-01 14:02:00 +02:00
h - > missing_fields + + ;
2016-05-09 15:58:32 +02:00
h - > cur_pic_ptr = NULL ;
h - > first_field = FIELD_PICTURE ( h ) ;
} else {
2016-07-01 14:02:00 +02:00
h - > missing_fields = 0 ;
2016-05-09 15:58:32 +02:00
if ( h - > cur_pic_ptr - > frame_num ! = h - > poc . frame_num ) {
2016-07-01 14:02:00 +02:00
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX ,
h - > picture_structure = = PICT_BOTTOM_FIELD ) ;
2016-05-09 15:58:32 +02:00
/* This and the previous field had different frame_nums.
* Consider this field first in pair . Throw away previous
* one except for reference purposes . */
h - > first_field = 1 ;
h - > cur_pic_ptr = NULL ;
} else {
/* Second field in complementary pair */
h - > first_field = 0 ;
}
}
} else {
/* Frame or first field in a potentially complementary pair */
h - > first_field = FIELD_PICTURE ( h ) ;
}
if ( ! FIELD_PICTURE ( h ) | | h - > first_field ) {
if ( h264_frame_start ( h ) < 0 ) {
h - > first_field = 0 ;
return AVERROR_INVALIDDATA ;
}
} else {
release_unused_pictures ( h , 0 ) ;
}
2016-07-01 14:02:00 +02:00
/* Some macroblocks can be accessed before they're available in case
* of lost slices , MBAFF or threading . */
if ( FIELD_PICTURE ( h ) ) {
for ( i = ( h - > picture_structure = = PICT_BOTTOM_FIELD ) ; i < h - > mb_height ; i + + )
memset ( h - > slice_table + i * h - > mb_stride , - 1 , ( h - > mb_stride - ( i + 1 = = h - > mb_height ) ) * sizeof ( * h - > slice_table ) ) ;
} else {
memset ( h - > slice_table , - 1 ,
( h - > mb_height * h - > mb_stride - 1 ) * sizeof ( * h - > slice_table ) ) ;
}
2016-05-09 15:58:32 +02:00
2016-05-17 19:00:18 +02:00
ff_h264_init_poc ( h - > cur_pic_ptr - > field_poc , & h - > cur_pic_ptr - > poc ,
h - > ps . sps , & h - > poc , h - > picture_structure , nal - > ref_idc ) ;
memcpy ( h - > mmco , sl - > mmco , sl - > nb_mmco * sizeof ( * h - > mmco ) ) ;
h - > nb_mmco = sl - > nb_mmco ;
h - > explicit_ref_marking = sl - > explicit_ref_marking ;
2016-05-18 07:27:32 +02:00
/* Set the frame properties/side data. Only done for the second field in
* field coded frames , since some SEI information is present for each field
* and is merged by the SEI parsing code . */
if ( ! FIELD_PICTURE ( h ) | | ! h - > first_field ) {
ret = h264_export_frame_props ( h ) ;
if ( ret < 0 )
return ret ;
}
2016-05-09 15:58:32 +02:00
return 0 ;
}
2016-05-17 16:45:15 +02:00
static int h264_slice_header_parse ( const H264Context * h , H264SliceContext * sl ,
2016-05-16 09:34:44 +02:00
const H2645NAL * nal )
2014-03-19 18:52:47 +03:00
{
2016-03-22 14:31:21 +02:00
const SPS * sps ;
const PPS * pps ;
2014-03-19 18:52:47 +03:00
int ret ;
2016-04-13 17:53:50 +02:00
unsigned int slice_type , tmp , i ;
2014-03-19 18:52:47 +03:00
int field_pic_flag , bottom_field_flag ;
2015-03-21 22:33:27 +02:00
int first_slice = sl = = h - > slice_ctx & & ! h - > current_slice ;
2016-07-27 17:28:00 +02:00
int picture_structure ;
2014-03-19 18:52:47 +03:00
2015-06-27 23:41:00 +02:00
if ( first_slice )
av_assert0 ( ! h - > setup_finished ) ;
2016-06-29 20:04:23 +02:00
sl - > first_mb_addr = get_ue_golomb_long ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
2015-01-27 15:39:06 +02:00
slice_type = get_ue_golomb_31 ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
if ( slice_type > 9 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
2015-01-17 23:28:46 +02:00
" slice type %d too large at %d \n " ,
2016-04-16 03:20:37 +02:00
slice_type , sl - > first_mb_addr ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
if ( slice_type > 4 ) {
slice_type - = 5 ;
2015-01-17 23:28:46 +02:00
sl - > slice_type_fixed = 1 ;
2014-03-19 18:52:47 +03:00
} else
2015-01-17 23:28:46 +02:00
sl - > slice_type_fixed = 0 ;
2014-03-19 18:52:47 +03:00
2013-08-19 15:24:45 +03:00
slice_type = ff_h264_golomb_to_pict_type [ slice_type ] ;
2015-01-17 23:28:46 +02:00
sl - > slice_type = slice_type ;
sl - > slice_type_nos = slice_type & 3 ;
2014-03-19 18:52:47 +03:00
2016-05-16 09:34:44 +02:00
if ( nal - > type = = NAL_IDR_SLICE & &
2015-01-17 23:28:46 +02:00
sl - > slice_type_nos ! = AV_PICTURE_TYPE_I ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR , " A non-intra slice in an IDR NAL unit. \n " ) ;
return AVERROR_INVALIDDATA ;
}
2016-05-12 14:37:35 +02:00
sl - > pps_id = get_ue_golomb ( & sl - > gb ) ;
if ( sl - > pps_id > = MAX_PPS_COUNT ) {
av_log ( h - > avctx , AV_LOG_ERROR , " pps_id %u out of range \n " , sl - > pps_id ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
2016-05-12 14:37:35 +02:00
if ( ! h - > ps . pps_list [ sl - > pps_id ] ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR ,
" non-existing PPS %u referenced \n " ,
2016-05-12 14:37:35 +02:00
sl - > pps_id ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
2016-05-12 14:37:35 +02:00
pps = ( const PPS * ) h - > ps . pps_list [ sl - > pps_id ] - > data ;
2015-02-06 16:09:54 +02:00
2016-06-12 13:24:27 +02:00
if ( ! h - > ps . sps_list [ pps - > sps_id ] ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR ,
2016-05-12 14:37:35 +02:00
" non-existing SPS %u referenced \n " , pps - > sps_id ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
2016-05-12 14:37:35 +02:00
sps = ( const SPS * ) h - > ps . sps_list [ pps - > sps_id ] - > data ;
2014-03-19 18:52:47 +03:00
2016-05-17 15:35:50 +02:00
sl - > frame_num = get_bits ( & sl - > gb , sps - > log2_max_frame_num ) ;
2015-02-07 03:06:20 +02:00
if ( ! first_slice ) {
2016-07-27 17:28:00 +02:00
if ( h - > poc . frame_num ! = sl - > frame_num ) {
2015-02-07 03:06:20 +02:00
av_log ( h - > avctx , AV_LOG_ERROR , " Frame num change from %d to %d \n " ,
2016-07-27 17:28:00 +02:00
h - > poc . frame_num , sl - > frame_num ) ;
2015-02-07 03:06:20 +02:00
return AVERROR_INVALIDDATA ;
}
}
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
sl - > mb_mbaff = 0 ;
2015-05-09 21:54:47 +02:00
2016-03-22 14:31:21 +02:00
if ( sps - > frame_mbs_only_flag ) {
2015-02-07 03:22:44 +02:00
picture_structure = PICT_FRAME ;
2014-03-19 18:52:47 +03:00
} else {
2016-07-02 19:22:34 +02:00
if ( ! sps - > direct_8x8_inference_flag & & slice_type = = AV_PICTURE_TYPE_B ) {
2014-03-24 03:24:55 +03:00
av_log ( h - > avctx , AV_LOG_ERROR , " This stream was generated by a broken encoder, invalid 8x8 inference \n " ) ;
return - 1 ;
}
2015-01-27 15:39:06 +02:00
field_pic_flag = get_bits1 ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
if ( field_pic_flag ) {
2015-01-27 15:39:06 +02:00
bottom_field_flag = get_bits1 ( & sl - > gb ) ;
2015-02-07 03:22:44 +02:00
picture_structure = PICT_TOP_FIELD + bottom_field_flag ;
2014-03-19 18:52:47 +03:00
} else {
2015-02-07 03:22:44 +02:00
picture_structure = PICT_FRAME ;
2014-03-19 18:52:47 +03:00
}
2015-02-07 03:22:44 +02:00
}
2016-07-01 14:02:00 +02:00
sl - > picture_structure = picture_structure ;
2015-03-21 18:30:59 +02:00
sl - > mb_field_decoding_flag = picture_structure ! = PICT_FRAME ;
2015-02-07 03:22:44 +02:00
2016-05-09 15:58:32 +02:00
if ( picture_structure = = PICT_FRAME ) {
2016-05-17 16:45:15 +02:00
sl - > curr_pic_num = sl - > frame_num ;
sl - > max_pic_num = 1 < < sps - > log2_max_frame_num ;
2014-03-19 18:52:47 +03:00
} else {
2016-05-17 16:45:15 +02:00
sl - > curr_pic_num = 2 * sl - > frame_num + 1 ;
sl - > max_pic_num = 1 < < ( sps - > log2_max_frame_num + 1 ) ;
2014-03-19 18:52:47 +03:00
}
2016-05-16 09:34:44 +02:00
if ( nal - > type = = NAL_IDR_SLICE )
2015-12-29 09:04:08 +02:00
get_ue_golomb_long ( & sl - > gb ) ; /* idr_pic_id */
2014-03-19 18:52:47 +03:00
2016-03-22 14:31:21 +02:00
if ( sps - > poc_type = = 0 ) {
2016-05-17 15:35:50 +02:00
sl - > poc_lsb = get_bits ( & sl - > gb , sps - > log2_max_poc_lsb ) ;
2014-03-19 18:52:47 +03:00
2016-05-17 15:35:50 +02:00
if ( pps - > pic_order_present = = 1 & & picture_structure = = PICT_FRAME )
sl - > delta_poc_bottom = get_se_golomb ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
}
2016-03-22 14:31:21 +02:00
if ( sps - > poc_type = = 1 & & ! sps - > delta_pic_order_always_zero_flag ) {
2016-05-17 15:35:50 +02:00
sl - > delta_poc [ 0 ] = get_se_golomb ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
2016-05-17 15:35:50 +02:00
if ( pps - > pic_order_present = = 1 & & picture_structure = = PICT_FRAME )
sl - > delta_poc [ 1 ] = get_se_golomb ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
}
2016-03-22 14:31:21 +02:00
if ( pps - > redundant_pic_cnt_present )
2015-01-27 15:39:06 +02:00
sl - > redundant_pic_count = get_ue_golomb ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
2016-03-21 17:25:29 +02:00
if ( sl - > slice_type_nos = = AV_PICTURE_TYPE_B )
sl - > direct_spatial_mv_pred = get_bits1 ( & sl - > gb ) ;
2016-03-21 17:14:31 +02:00
ret = ff_h264_parse_ref_count ( & sl - > list_count , sl - > ref_count ,
2016-03-22 14:31:21 +02:00
& sl - > gb , pps , sl - > slice_type_nos ,
2016-07-01 14:02:00 +02:00
picture_structure , h - > avctx ) ;
2014-03-19 18:52:47 +03:00
if ( ret < 0 )
return ret ;
2015-01-17 23:28:46 +02:00
if ( sl - > slice_type_nos ! = AV_PICTURE_TYPE_I ) {
2015-01-17 23:28:46 +02:00
ret = ff_h264_decode_ref_pic_list_reordering ( h , sl ) ;
2014-03-19 18:52:47 +03:00
if ( ret < 0 ) {
2015-01-17 23:28:46 +02:00
sl - > ref_count [ 1 ] = sl - > ref_count [ 0 ] = 0 ;
2014-03-19 18:52:47 +03:00
return ret ;
}
}
2016-04-14 20:53:59 +02:00
sl - > pwt . use_weight = 0 ;
for ( i = 0 ; i < 2 ; i + + ) {
sl - > pwt . luma_weight_flag [ i ] = 0 ;
sl - > pwt . chroma_weight_flag [ i ] = 0 ;
}
2016-03-22 14:31:21 +02:00
if ( ( pps - > weighted_pred & & sl - > slice_type_nos = = AV_PICTURE_TYPE_P ) | |
( pps - > weighted_bipred_idc = = 1 & &
2015-01-17 23:28:46 +02:00
sl - > slice_type_nos = = AV_PICTURE_TYPE_B ) )
2016-03-22 14:31:21 +02:00
ff_h264_pred_weight_table ( & sl - > gb , sps , sl - > ref_count ,
2016-06-20 10:28:17 +02:00
sl - > slice_type_nos , & sl - > pwt , h - > avctx ) ;
2014-03-19 18:52:47 +03:00
2016-05-09 14:25:56 +02:00
sl - > explicit_ref_marking = 0 ;
2016-05-16 09:34:44 +02:00
if ( nal - > ref_idc ) {
2016-05-09 13:48:01 +02:00
ret = ff_h264_decode_ref_pic_marking ( h , sl , & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
if ( ret < 0 & & ( h - > avctx - > err_recognition & AV_EF_EXPLODE ) )
return AVERROR_INVALIDDATA ;
}
2016-03-22 14:31:21 +02:00
if ( sl - > slice_type_nos ! = AV_PICTURE_TYPE_I & & pps - > cabac ) {
2015-01-27 15:39:06 +02:00
tmp = get_ue_golomb_31 ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
if ( tmp > 2 ) {
av_log ( h - > avctx , AV_LOG_ERROR , " cabac_init_idc %u overflow \n " , tmp ) ;
return AVERROR_INVALIDDATA ;
}
2015-01-17 23:28:46 +02:00
sl - > cabac_init_idc = tmp ;
2014-03-19 18:52:47 +03:00
}
2015-01-17 23:28:46 +02:00
sl - > last_qscale_diff = 0 ;
2016-03-22 14:31:21 +02:00
tmp = pps - > init_qp + get_se_golomb ( & sl - > gb ) ;
if ( tmp > 51 + 6 * ( sps - > bit_depth_luma - 8 ) ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR , " QP %u out of range \n " , tmp ) ;
return AVERROR_INVALIDDATA ;
}
2015-01-17 23:28:46 +02:00
sl - > qscale = tmp ;
2016-05-12 14:25:52 +02:00
sl - > chroma_qp [ 0 ] = get_chroma_qp ( pps , 0 , sl - > qscale ) ;
sl - > chroma_qp [ 1 ] = get_chroma_qp ( pps , 1 , sl - > qscale ) ;
2014-03-19 18:52:47 +03:00
// FIXME qscale / qp ... stuff
2015-01-17 23:28:46 +02:00
if ( sl - > slice_type = = AV_PICTURE_TYPE_SP )
2015-01-27 15:39:06 +02:00
get_bits1 ( & sl - > gb ) ; /* sp_for_switch_flag */
2015-01-17 23:28:46 +02:00
if ( sl - > slice_type = = AV_PICTURE_TYPE_SP | |
sl - > slice_type = = AV_PICTURE_TYPE_SI )
2015-01-27 15:39:06 +02:00
get_se_golomb ( & sl - > gb ) ; /* slice_qs_delta */
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
sl - > deblocking_filter = 1 ;
sl - > slice_alpha_c0_offset = 0 ;
sl - > slice_beta_offset = 0 ;
2016-03-22 14:31:21 +02:00
if ( pps - > deblocking_filter_parameters_present ) {
2015-01-27 15:39:06 +02:00
tmp = get_ue_golomb_31 ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
if ( tmp > 2 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" deblocking_filter_idc %u out of range \n " , tmp ) ;
return AVERROR_INVALIDDATA ;
}
2015-01-17 23:28:46 +02:00
sl - > deblocking_filter = tmp ;
if ( sl - > deblocking_filter < 2 )
sl - > deblocking_filter ^ = 1 ; // 1<->0
if ( sl - > deblocking_filter ) {
2015-01-27 15:39:06 +02:00
sl - > slice_alpha_c0_offset = get_se_golomb ( & sl - > gb ) * 2 ;
sl - > slice_beta_offset = get_se_golomb ( & sl - > gb ) * 2 ;
2015-01-17 23:28:46 +02:00
if ( sl - > slice_alpha_c0_offset > 12 | |
sl - > slice_alpha_c0_offset < - 12 | |
sl - > slice_beta_offset > 12 | |
sl - > slice_beta_offset < - 12 ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR ,
" deblocking filter parameters %d %d out of range \n " ,
2015-01-17 23:28:46 +02:00
sl - > slice_alpha_c0_offset , sl - > slice_beta_offset ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
}
}
2016-04-13 17:53:50 +02:00
return 0 ;
}
/**
* Decode a slice header .
* This will ( re ) initialize the decoder and call h264_frame_start ( ) as needed .
*
* @ param h h264context
*
* @ return 0 if okay , < 0 if an error occurred
*/
2016-05-16 09:34:44 +02:00
int ff_h264_decode_slice_header ( H264Context * h , H264SliceContext * sl ,
const H2645NAL * nal )
2016-04-13 17:53:50 +02:00
{
int i , j , ret = 0 ;
2016-07-19 22:31:56 +02:00
int first_slice = sl = = h - > slice_ctx & & ! h - > current_slice ;
2016-04-13 17:53:50 +02:00
2016-05-16 09:34:44 +02:00
ret = h264_slice_header_parse ( h , sl , nal ) ;
2016-04-13 17:53:50 +02:00
if ( ret < 0 )
return ret ;
2016-07-27 18:22:41 +02:00
if ( sl - > first_mb_addr = = 0 | | ! h - > current_slice ) {
if ( h - > setup_finished ) {
av_log ( h - > avctx , AV_LOG_ERROR , " Too many fields \n " ) ;
return AVERROR_INVALIDDATA ;
}
}
2016-05-17 14:51:01 +02:00
if ( sl - > first_mb_addr = = 0 ) { // FIXME better field boundary detection
2016-07-27 16:11:02 +02:00
if ( h - > current_slice ) {
if ( h - > max_contexts > 1 ) {
if ( ! h - > single_decode_warning ) {
av_log ( h - > avctx , AV_LOG_WARNING , " Cannot decode multiple access units as slice threads \n " ) ;
h - > single_decode_warning = 1 ;
}
h - > max_contexts = 1 ;
return SLICE_SINGLETHREAD ;
}
if ( h - > cur_pic_ptr & & FIELD_PICTURE ( h ) & & h - > first_field ) {
ret = ff_h264_field_end ( h , h - > slice_ctx , 1 ) ;
h - > current_slice = 0 ;
if ( ret < 0 )
return ret ;
} else if ( h - > cur_pic_ptr & & ! FIELD_PICTURE ( h ) & & ! h - > first_field & & h - > nal_unit_type = = NAL_IDR_SLICE ) {
av_log ( h , AV_LOG_WARNING , " Broken frame packetizing \n " ) ;
ret = ff_h264_field_end ( h , h - > slice_ctx , 1 ) ;
h - > current_slice = 0 ;
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX , 0 ) ;
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX , 1 ) ;
h - > cur_pic_ptr = NULL ;
if ( ret < 0 )
return ret ;
} else
return AVERROR_INVALIDDATA ;
2016-05-17 14:51:01 +02:00
}
if ( ! h - > first_field ) {
if ( h - > cur_pic_ptr & & ! h - > droppable ) {
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , INT_MAX ,
h - > picture_structure = = PICT_BOTTOM_FIELD ) ;
}
h - > cur_pic_ptr = NULL ;
}
}
2016-07-27 16:11:02 +02:00
if ( ! h - > current_slice )
av_assert0 ( sl = = h - > slice_ctx ) ;
if ( h - > current_slice = = 0 & & ! h - > first_field ) {
if (
( h - > avctx - > skip_frame > = AVDISCARD_NONREF & & ! h - > nal_ref_idc ) | |
( h - > avctx - > skip_frame > = AVDISCARD_BIDIR & & sl - > slice_type_nos = = AV_PICTURE_TYPE_B ) | |
( h - > avctx - > skip_frame > = AVDISCARD_NONINTRA & & sl - > slice_type_nos ! = AV_PICTURE_TYPE_I ) | |
( h - > avctx - > skip_frame > = AVDISCARD_NONKEY & & h - > nal_unit_type ! = NAL_IDR_SLICE & & h - > sei . recovery_point . recovery_frame_cnt < 0 ) | |
h - > avctx - > skip_frame > = AVDISCARD_ALL ) {
return SLICE_SKIPED ;
}
}
if ( ! first_slice ) {
const PPS * pps = ( const PPS * ) h - > ps . pps_list [ sl - > pps_id ] - > data ;
if ( h - > ps . pps - > sps_id ! = pps - > sps_id | |
h - > ps . pps - > transform_8x8_mode ! = pps - > transform_8x8_mode /*||
( h - > setup_finished & & h - > ps . pps ! = pps ) */ ) {
2016-05-17 14:51:01 +02:00
av_log ( h - > avctx , AV_LOG_ERROR , " PPS changed between slices \n " ) ;
return AVERROR_INVALIDDATA ;
}
2016-07-27 16:11:02 +02:00
if ( h - > ps . sps ! = ( const SPS * ) h - > ps . sps_list [ h - > ps . pps - > sps_id ] - > data ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" SPS changed in the middle of the frame \n " ) ;
return AVERROR_INVALIDDATA ;
}
}
2016-05-17 14:51:01 +02:00
2016-05-09 15:58:32 +02:00
if ( h - > current_slice = = 0 ) {
2016-07-19 22:31:56 +02:00
ret = h264_field_start ( h , sl , nal , first_slice ) ;
2016-05-09 15:58:32 +02:00
if ( ret < 0 )
return ret ;
2016-07-27 16:11:02 +02:00
} else {
2016-05-17 14:51:01 +02:00
if ( h - > picture_structure ! = sl - > picture_structure | |
h - > droppable ! = ( nal - > ref_idc = = 0 ) ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" Changing field mode (%d -> %d) between slices is not allowed \n " ,
h - > picture_structure , sl - > picture_structure ) ;
return AVERROR_INVALIDDATA ;
} else if ( ! h - > cur_pic_ptr ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
" unset cur_pic_ptr on slice %d \n " ,
h - > current_slice + 1 ) ;
return AVERROR_INVALIDDATA ;
}
2016-05-09 15:58:32 +02:00
}
2016-06-29 20:04:23 +02:00
av_assert1 ( h - > mb_num = = h - > mb_width * h - > mb_height ) ;
2016-04-16 03:20:37 +02:00
if ( sl - > first_mb_addr < < FIELD_OR_MBAFF_PICTURE ( h ) > = h - > mb_num | |
sl - > first_mb_addr > = h - > mb_num ) {
av_log ( h - > avctx , AV_LOG_ERROR , " first_mb_in_slice overflow \n " ) ;
return AVERROR_INVALIDDATA ;
}
sl - > resync_mb_x = sl - > mb_x = sl - > first_mb_addr % h - > mb_width ;
sl - > resync_mb_y = sl - > mb_y = ( sl - > first_mb_addr / h - > mb_width ) < <
FIELD_OR_MBAFF_PICTURE ( h ) ;
if ( h - > picture_structure = = PICT_BOTTOM_FIELD )
sl - > resync_mb_y = sl - > mb_y = sl - > mb_y + 1 ;
2016-06-29 20:04:23 +02:00
av_assert1 ( sl - > mb_y < h - > mb_height ) ;
2016-04-16 03:20:37 +02:00
2016-04-14 20:53:59 +02:00
ret = ff_h264_build_ref_list ( h , sl ) ;
if ( ret < 0 )
return ret ;
2016-04-14 20:53:59 +02:00
if ( h - > ps . pps - > weighted_bipred_idc = = 2 & &
sl - > slice_type_nos = = AV_PICTURE_TYPE_B ) {
implicit_weight_table ( h , sl , - 1 ) ;
if ( FRAME_MBAFF ( h ) ) {
implicit_weight_table ( h , sl , 0 ) ;
implicit_weight_table ( h , sl , 1 ) ;
}
}
2016-04-14 20:53:59 +02:00
if ( sl - > slice_type_nos = = AV_PICTURE_TYPE_B & & ! sl - > direct_spatial_mv_pred )
ff_h264_direct_dist_scale_factor ( h , sl ) ;
ff_h264_direct_ref_list_init ( h , sl ) ;
2014-03-19 18:52:47 +03:00
if ( h - > avctx - > skip_loop_filter > = AVDISCARD_ALL | |
2014-06-07 21:56:19 +03:00
( h - > avctx - > skip_loop_filter > = AVDISCARD_NONKEY & &
h - > nal_unit_type ! = NAL_IDR_SLICE ) | |
2014-06-07 21:56:18 +03:00
( h - > avctx - > skip_loop_filter > = AVDISCARD_NONINTRA & &
2015-01-17 23:28:46 +02:00
sl - > slice_type_nos ! = AV_PICTURE_TYPE_I ) | |
2014-03-19 18:52:47 +03:00
( h - > avctx - > skip_loop_filter > = AVDISCARD_BIDIR & &
2015-01-17 23:28:46 +02:00
sl - > slice_type_nos = = AV_PICTURE_TYPE_B ) | |
2014-03-19 18:52:47 +03:00
( h - > avctx - > skip_loop_filter > = AVDISCARD_NONREF & &
2016-05-16 09:34:44 +02:00
nal - > ref_idc = = 0 ) )
2015-01-17 23:28:46 +02:00
sl - > deblocking_filter = 0 ;
2014-03-19 18:52:47 +03:00
2015-01-28 14:26:24 +02:00
if ( sl - > deblocking_filter = = 1 & & h - > max_contexts > 1 ) {
2015-06-29 21:59:37 +02:00
if ( h - > avctx - > flags2 & AV_CODEC_FLAG2_FAST ) {
2014-03-19 18:52:47 +03:00
/* Cheat slightly for speed:
* Do not bother to deblock across slices . */
2015-01-17 23:28:46 +02:00
sl - > deblocking_filter = 2 ;
2014-03-19 18:52:47 +03:00
} else {
2016-04-13 13:52:36 +02:00
h - > postpone_filter = 1 ;
2014-03-19 18:52:47 +03:00
}
}
2015-01-17 23:28:46 +02:00
sl - > qp_thresh = 15 -
2015-01-17 23:28:46 +02:00
FFMIN ( sl - > slice_alpha_c0_offset , sl - > slice_beta_offset ) -
2014-03-19 18:52:47 +03:00
FFMAX3 ( 0 ,
2016-04-13 17:53:50 +02:00
h - > ps . pps - > chroma_qp_index_offset [ 0 ] ,
h - > ps . pps - > chroma_qp_index_offset [ 1 ] ) +
6 * ( h - > ps . sps - > bit_depth_luma - 8 ) ;
2014-03-19 18:52:47 +03:00
2015-01-28 14:26:24 +02:00
sl - > slice_num = + + h - > current_slice ;
2014-03-24 03:24:55 +03:00
2015-03-21 15:30:19 +02:00
if ( sl - > slice_num )
2015-03-21 22:33:27 +02:00
h - > slice_row [ ( sl - > slice_num - 1 ) & ( MAX_SLICES - 1 ) ] = sl - > resync_mb_y ;
if ( h - > slice_row [ sl - > slice_num & ( MAX_SLICES - 1 ) ] + 3 > = sl - > resync_mb_y
& & h - > slice_row [ sl - > slice_num & ( MAX_SLICES - 1 ) ] < = sl - > resync_mb_y
2015-03-21 15:30:19 +02:00
& & sl - > slice_num > = MAX_SLICES ) {
2014-03-24 03:24:55 +03:00
//in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case
2015-03-21 15:30:19 +02:00
av_log ( h - > avctx , AV_LOG_WARNING , " Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts \n " , sl - > slice_num , MAX_SLICES ) ;
2014-03-19 18:52:47 +03:00
}
for ( j = 0 ; j < 2 ; j + + ) {
int id_list [ 16 ] ;
2016-04-13 13:52:36 +02:00
int * ref2frm = h - > ref2frm [ sl - > slice_num & ( MAX_SLICES - 1 ) ] [ j ] ;
2014-03-19 18:52:47 +03:00
for ( i = 0 ; i < 16 ; i + + ) {
id_list [ i ] = 60 ;
2015-01-17 23:28:46 +02:00
if ( j < sl - > list_count & & i < sl - > ref_count [ j ] & &
2015-04-17 12:09:50 +02:00
sl - > ref_list [ j ] [ i ] . parent - > f - > buf [ 0 ] ) {
2014-03-19 18:52:47 +03:00
int k ;
2015-04-17 12:09:50 +02:00
AVBuffer * buf = sl - > ref_list [ j ] [ i ] . parent - > f - > buf [ 0 ] - > buffer ;
2014-03-19 18:52:47 +03:00
for ( k = 0 ; k < h - > short_ref_count ; k + + )
2015-04-17 12:09:50 +02:00
if ( h - > short_ref [ k ] - > f - > buf [ 0 ] - > buffer = = buf ) {
2014-03-19 18:52:47 +03:00
id_list [ i ] = k ;
break ;
}
for ( k = 0 ; k < h - > long_ref_count ; k + + )
2015-04-17 12:09:50 +02:00
if ( h - > long_ref [ k ] & & h - > long_ref [ k ] - > f - > buf [ 0 ] - > buffer = = buf ) {
2014-03-19 18:52:47 +03:00
id_list [ i ] = h - > short_ref_count + k ;
break ;
}
}
}
ref2frm [ 0 ] =
ref2frm [ 1 ] = - 1 ;
for ( i = 0 ; i < 16 ; i + + )
2015-01-17 23:28:46 +02:00
ref2frm [ i + 2 ] = 4 * id_list [ i ] + ( sl - > ref_list [ j ] [ i ] . reference & 3 ) ;
2014-03-19 18:52:47 +03:00
ref2frm [ 18 + 0 ] =
ref2frm [ 18 + 1 ] = - 1 ;
for ( i = 16 ; i < 48 ; i + + )
ref2frm [ i + 4 ] = 4 * id_list [ ( i - 16 ) > > 1 ] +
2015-01-17 23:28:46 +02:00
( sl - > ref_list [ j ] [ i ] . reference & 3 ) ;
2014-03-19 18:52:47 +03:00
}
if ( h - > avctx - > debug & FF_DEBUG_PICT_INFO ) {
av_log ( h - > avctx , AV_LOG_DEBUG ,
2016-04-13 17:53:50 +02:00
" slice:%d %s mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s \n " ,
2015-01-17 23:28:46 +02:00
sl - > slice_num ,
2014-03-19 18:52:47 +03:00
( h - > picture_structure = = PICT_FRAME ? " F " : h - > picture_structure = = PICT_TOP_FIELD ? " T " : " B " ) ,
2016-04-13 17:53:50 +02:00
sl - > mb_y * h - > mb_width + sl - > mb_x ,
2015-01-17 23:28:46 +02:00
av_get_picture_type_char ( sl - > slice_type ) ,
sl - > slice_type_fixed ? " fix " : " " ,
2016-05-16 09:34:44 +02:00
nal - > type = = NAL_IDR_SLICE ? " IDR " : " " ,
2016-04-13 17:53:50 +02:00
h - > poc . frame_num ,
2014-03-19 18:52:47 +03:00
h - > cur_pic_ptr - > field_poc [ 0 ] ,
h - > cur_pic_ptr - > field_poc [ 1 ] ,
2015-01-17 23:28:46 +02:00
sl - > ref_count [ 0 ] , sl - > ref_count [ 1 ] ,
2015-01-17 23:28:46 +02:00
sl - > qscale ,
2015-01-17 23:28:46 +02:00
sl - > deblocking_filter ,
sl - > slice_alpha_c0_offset , sl - > slice_beta_offset ,
2016-03-21 17:14:31 +02:00
sl - > pwt . use_weight ,
sl - > pwt . use_weight = = 1 & & sl - > pwt . use_weight_chroma ? " c " : " " ,
2015-01-17 23:28:46 +02:00
sl - > slice_type = = AV_PICTURE_TYPE_B ? ( sl - > direct_spatial_mv_pred ? " SPAT " : " TEMP " ) : " " ) ;
2014-03-19 18:52:47 +03:00
}
return 0 ;
}
2015-01-17 23:28:46 +02:00
int ff_h264_get_slice_type ( const H264SliceContext * sl )
2014-03-19 18:52:47 +03:00
{
2015-01-17 23:28:46 +02:00
switch ( sl - > slice_type ) {
2014-03-19 18:52:47 +03:00
case AV_PICTURE_TYPE_P :
return 0 ;
case AV_PICTURE_TYPE_B :
return 1 ;
case AV_PICTURE_TYPE_I :
return 2 ;
case AV_PICTURE_TYPE_SP :
return 3 ;
case AV_PICTURE_TYPE_SI :
return 4 ;
default :
return AVERROR_INVALIDDATA ;
}
}
2015-01-28 14:24:32 +02:00
static av_always_inline void fill_filter_caches_inter ( const H264Context * h ,
2015-01-17 23:28:46 +02:00
H264SliceContext * sl ,
2014-03-19 18:52:47 +03:00
int mb_type , int top_xy ,
int left_xy [ LEFT_MBS ] ,
int top_type ,
int left_type [ LEFT_MBS ] ,
int mb_xy , int list )
{
int b_stride = h - > b_stride ;
2015-01-17 23:28:46 +02:00
int16_t ( * mv_dst ) [ 2 ] = & sl - > mv_cache [ list ] [ scan8 [ 0 ] ] ;
int8_t * ref_cache = & sl - > ref_cache [ list ] [ scan8 [ 0 ] ] ;
2014-03-19 18:52:47 +03:00
if ( IS_INTER ( mb_type ) | | IS_DIRECT ( mb_type ) ) {
if ( USES_LIST ( top_type , list ) ) {
const int b_xy = h - > mb2b_xy [ top_xy ] + 3 * b_stride ;
const int b8_xy = 4 * top_xy + 2 ;
2016-06-21 10:09:19 +02:00
const int * ref2frm = h - > ref2frm [ h - > slice_table [ top_xy ] & ( MAX_SLICES - 1 ) ] [ list ] + ( MB_MBAFF ( sl ) ? 20 : 2 ) ;
2014-03-19 18:52:47 +03:00
AV_COPY128 ( mv_dst - 1 * 8 , h - > cur_pic . motion_val [ list ] [ b_xy + 0 ] ) ;
ref_cache [ 0 - 1 * 8 ] =
2015-12-17 23:51:00 +02:00
ref_cache [ 1 - 1 * 8 ] = ref2frm [ h - > cur_pic . ref_index [ list ] [ b8_xy + 0 ] ] ;
2014-03-19 18:52:47 +03:00
ref_cache [ 2 - 1 * 8 ] =
2015-12-17 23:51:00 +02:00
ref_cache [ 3 - 1 * 8 ] = ref2frm [ h - > cur_pic . ref_index [ list ] [ b8_xy + 1 ] ] ;
2014-03-19 18:52:47 +03:00
} else {
AV_ZERO128 ( mv_dst - 1 * 8 ) ;
AV_WN32A ( & ref_cache [ 0 - 1 * 8 ] , ( ( LIST_NOT_USED ) & 0xFF ) * 0x01010101u ) ;
}
if ( ! IS_INTERLACED ( mb_type ^ left_type [ LTOP ] ) ) {
if ( USES_LIST ( left_type [ LTOP ] , list ) ) {
const int b_xy = h - > mb2b_xy [ left_xy [ LTOP ] ] + 3 ;
const int b8_xy = 4 * left_xy [ LTOP ] + 1 ;
2016-06-21 10:09:19 +02:00
const int * ref2frm = h - > ref2frm [ h - > slice_table [ left_xy [ LTOP ] ] & ( MAX_SLICES - 1 ) ] [ list ] + ( MB_MBAFF ( sl ) ? 20 : 2 ) ;
2014-03-19 18:52:47 +03:00
AV_COPY32 ( mv_dst - 1 + 0 , h - > cur_pic . motion_val [ list ] [ b_xy + b_stride * 0 ] ) ;
AV_COPY32 ( mv_dst - 1 + 8 , h - > cur_pic . motion_val [ list ] [ b_xy + b_stride * 1 ] ) ;
AV_COPY32 ( mv_dst - 1 + 16 , h - > cur_pic . motion_val [ list ] [ b_xy + b_stride * 2 ] ) ;
AV_COPY32 ( mv_dst - 1 + 24 , h - > cur_pic . motion_val [ list ] [ b_xy + b_stride * 3 ] ) ;
ref_cache [ - 1 + 0 ] =
2015-12-17 23:51:00 +02:00
ref_cache [ - 1 + 8 ] = ref2frm [ h - > cur_pic . ref_index [ list ] [ b8_xy + 2 * 0 ] ] ;
2014-03-19 18:52:47 +03:00
ref_cache [ - 1 + 16 ] =
2015-12-17 23:51:00 +02:00
ref_cache [ - 1 + 24 ] = ref2frm [ h - > cur_pic . ref_index [ list ] [ b8_xy + 2 * 1 ] ] ;
2014-03-19 18:52:47 +03:00
} else {
AV_ZERO32 ( mv_dst - 1 + 0 ) ;
AV_ZERO32 ( mv_dst - 1 + 8 ) ;
AV_ZERO32 ( mv_dst - 1 + 16 ) ;
AV_ZERO32 ( mv_dst - 1 + 24 ) ;
ref_cache [ - 1 + 0 ] =
ref_cache [ - 1 + 8 ] =
ref_cache [ - 1 + 16 ] =
ref_cache [ - 1 + 24 ] = LIST_NOT_USED ;
}
}
}
if ( ! USES_LIST ( mb_type , list ) ) {
fill_rectangle ( mv_dst , 4 , 4 , 8 , pack16to32 ( 0 , 0 ) , 4 ) ;
AV_WN32A ( & ref_cache [ 0 * 8 ] , ( ( LIST_NOT_USED ) & 0xFF ) * 0x01010101u ) ;
AV_WN32A ( & ref_cache [ 1 * 8 ] , ( ( LIST_NOT_USED ) & 0xFF ) * 0x01010101u ) ;
AV_WN32A ( & ref_cache [ 2 * 8 ] , ( ( LIST_NOT_USED ) & 0xFF ) * 0x01010101u ) ;
AV_WN32A ( & ref_cache [ 3 * 8 ] , ( ( LIST_NOT_USED ) & 0xFF ) * 0x01010101u ) ;
return ;
}
{
int8_t * ref = & h - > cur_pic . ref_index [ list ] [ 4 * mb_xy ] ;
2016-06-21 10:09:19 +02:00
const int * ref2frm = h - > ref2frm [ sl - > slice_num & ( MAX_SLICES - 1 ) ] [ list ] + ( MB_MBAFF ( sl ) ? 20 : 2 ) ;
2015-12-17 23:51:00 +02:00
uint32_t ref01 = ( pack16to32 ( ref2frm [ ref [ 0 ] ] , ref2frm [ ref [ 1 ] ] ) & 0x00FF00FF ) * 0x0101 ;
uint32_t ref23 = ( pack16to32 ( ref2frm [ ref [ 2 ] ] , ref2frm [ ref [ 3 ] ] ) & 0x00FF00FF ) * 0x0101 ;
2014-03-19 18:52:47 +03:00
AV_WN32A ( & ref_cache [ 0 * 8 ] , ref01 ) ;
AV_WN32A ( & ref_cache [ 1 * 8 ] , ref01 ) ;
AV_WN32A ( & ref_cache [ 2 * 8 ] , ref23 ) ;
AV_WN32A ( & ref_cache [ 3 * 8 ] , ref23 ) ;
}
{
2015-01-17 23:28:46 +02:00
int16_t ( * mv_src ) [ 2 ] = & h - > cur_pic . motion_val [ list ] [ 4 * sl - > mb_x + 4 * sl - > mb_y * b_stride ] ;
2014-03-19 18:52:47 +03:00
AV_COPY128 ( mv_dst + 8 * 0 , mv_src + 0 * b_stride ) ;
AV_COPY128 ( mv_dst + 8 * 1 , mv_src + 1 * b_stride ) ;
AV_COPY128 ( mv_dst + 8 * 2 , mv_src + 2 * b_stride ) ;
AV_COPY128 ( mv_dst + 8 * 3 , mv_src + 3 * b_stride ) ;
}
}
/**
* @ return non zero if the loop filter can be skipped
*/
2015-01-28 14:24:32 +02:00
static int fill_filter_caches ( const H264Context * h , H264SliceContext * sl , int mb_type )
2014-03-19 18:52:47 +03:00
{
2015-01-17 23:28:46 +02:00
const int mb_xy = sl - > mb_xy ;
2014-03-19 18:52:47 +03:00
int top_xy , left_xy [ LEFT_MBS ] ;
int top_type , left_type [ LEFT_MBS ] ;
uint8_t * nnz ;
uint8_t * nnz_cache ;
2015-01-17 23:28:46 +02:00
top_xy = mb_xy - ( h - > mb_stride < < MB_FIELD ( sl ) ) ;
2014-03-19 18:52:47 +03:00
left_xy [ LBOT ] = left_xy [ LTOP ] = mb_xy - 1 ;
if ( FRAME_MBAFF ( h ) ) {
const int left_mb_field_flag = IS_INTERLACED ( h - > cur_pic . mb_type [ mb_xy - 1 ] ) ;
const int curr_mb_field_flag = IS_INTERLACED ( mb_type ) ;
2015-01-17 23:28:46 +02:00
if ( sl - > mb_y & 1 ) {
2014-03-19 18:52:47 +03:00
if ( left_mb_field_flag ! = curr_mb_field_flag )
left_xy [ LTOP ] - = h - > mb_stride ;
} else {
if ( curr_mb_field_flag )
top_xy + = h - > mb_stride &
( ( ( h - > cur_pic . mb_type [ top_xy ] > > 7 ) & 1 ) - 1 ) ;
if ( left_mb_field_flag ! = curr_mb_field_flag )
left_xy [ LBOT ] + = h - > mb_stride ;
}
}
2015-01-17 23:28:46 +02:00
sl - > top_mb_xy = top_xy ;
sl - > left_mb_xy [ LTOP ] = left_xy [ LTOP ] ;
sl - > left_mb_xy [ LBOT ] = left_xy [ LBOT ] ;
2014-03-19 18:52:47 +03:00
{
/* For sufficiently low qp, filtering wouldn't do anything.
* This is a conservative estimate : could also check beta_offset
* and more accurate chroma_qp . */
2015-01-17 23:28:46 +02:00
int qp_thresh = sl - > qp_thresh ; // FIXME strictly we should store qp_thresh for each mb of a slice
2014-03-19 18:52:47 +03:00
int qp = h - > cur_pic . qscale_table [ mb_xy ] ;
if ( qp < = qp_thresh & &
( left_xy [ LTOP ] < 0 | |
( ( qp + h - > cur_pic . qscale_table [ left_xy [ LTOP ] ] + 1 ) > > 1 ) < = qp_thresh ) & &
( top_xy < 0 | |
( ( qp + h - > cur_pic . qscale_table [ top_xy ] + 1 ) > > 1 ) < = qp_thresh ) ) {
if ( ! FRAME_MBAFF ( h ) )
return 1 ;
if ( ( left_xy [ LTOP ] < 0 | |
( ( qp + h - > cur_pic . qscale_table [ left_xy [ LBOT ] ] + 1 ) > > 1 ) < = qp_thresh ) & &
( top_xy < h - > mb_stride | |
( ( qp + h - > cur_pic . qscale_table [ top_xy - h - > mb_stride ] + 1 ) > > 1 ) < = qp_thresh ) )
return 1 ;
}
}
top_type = h - > cur_pic . mb_type [ top_xy ] ;
left_type [ LTOP ] = h - > cur_pic . mb_type [ left_xy [ LTOP ] ] ;
left_type [ LBOT ] = h - > cur_pic . mb_type [ left_xy [ LBOT ] ] ;
2015-01-17 23:28:46 +02:00
if ( sl - > deblocking_filter = = 2 ) {
2015-01-17 23:28:46 +02:00
if ( h - > slice_table [ top_xy ] ! = sl - > slice_num )
2014-03-19 18:52:47 +03:00
top_type = 0 ;
2015-01-17 23:28:46 +02:00
if ( h - > slice_table [ left_xy [ LBOT ] ] ! = sl - > slice_num )
2014-03-19 18:52:47 +03:00
left_type [ LTOP ] = left_type [ LBOT ] = 0 ;
} else {
if ( h - > slice_table [ top_xy ] = = 0xFFFF )
top_type = 0 ;
if ( h - > slice_table [ left_xy [ LBOT ] ] = = 0xFFFF )
left_type [ LTOP ] = left_type [ LBOT ] = 0 ;
}
2015-01-17 23:28:46 +02:00
sl - > top_type = top_type ;
sl - > left_type [ LTOP ] = left_type [ LTOP ] ;
sl - > left_type [ LBOT ] = left_type [ LBOT ] ;
2014-03-19 18:52:47 +03:00
if ( IS_INTRA ( mb_type ) )
return 0 ;
2015-01-17 23:28:46 +02:00
fill_filter_caches_inter ( h , sl , mb_type , top_xy , left_xy ,
2014-03-19 18:52:47 +03:00
top_type , left_type , mb_xy , 0 ) ;
2015-01-17 23:28:46 +02:00
if ( sl - > list_count = = 2 )
2015-01-17 23:28:46 +02:00
fill_filter_caches_inter ( h , sl , mb_type , top_xy , left_xy ,
2014-03-19 18:52:47 +03:00
top_type , left_type , mb_xy , 1 ) ;
nnz = h - > non_zero_count [ mb_xy ] ;
2015-01-17 23:28:46 +02:00
nnz_cache = sl - > non_zero_count_cache ;
2014-03-19 18:52:47 +03:00
AV_COPY32 ( & nnz_cache [ 4 + 8 * 1 ] , & nnz [ 0 ] ) ;
AV_COPY32 ( & nnz_cache [ 4 + 8 * 2 ] , & nnz [ 4 ] ) ;
AV_COPY32 ( & nnz_cache [ 4 + 8 * 3 ] , & nnz [ 8 ] ) ;
AV_COPY32 ( & nnz_cache [ 4 + 8 * 4 ] , & nnz [ 12 ] ) ;
2015-01-17 23:28:46 +02:00
sl - > cbp = h - > cbp_table [ mb_xy ] ;
2014-03-19 18:52:47 +03:00
if ( top_type ) {
nnz = h - > non_zero_count [ top_xy ] ;
AV_COPY32 ( & nnz_cache [ 4 + 8 * 0 ] , & nnz [ 3 * 4 ] ) ;
}
if ( left_type [ LTOP ] ) {
nnz = h - > non_zero_count [ left_xy [ LTOP ] ] ;
nnz_cache [ 3 + 8 * 1 ] = nnz [ 3 + 0 * 4 ] ;
nnz_cache [ 3 + 8 * 2 ] = nnz [ 3 + 1 * 4 ] ;
nnz_cache [ 3 + 8 * 3 ] = nnz [ 3 + 2 * 4 ] ;
nnz_cache [ 3 + 8 * 4 ] = nnz [ 3 + 3 * 4 ] ;
}
/* CAVLC 8x8dct requires NNZ values for residual decoding that differ
* from what the loop filter needs */
2016-03-22 14:31:21 +02:00
if ( ! CABAC ( h ) & & h - > ps . pps - > transform_8x8_mode ) {
2014-03-19 18:52:47 +03:00
if ( IS_8x8DCT ( top_type ) ) {
nnz_cache [ 4 + 8 * 0 ] =
nnz_cache [ 5 + 8 * 0 ] = ( h - > cbp_table [ top_xy ] & 0x4000 ) > > 12 ;
nnz_cache [ 6 + 8 * 0 ] =
nnz_cache [ 7 + 8 * 0 ] = ( h - > cbp_table [ top_xy ] & 0x8000 ) > > 12 ;
}
if ( IS_8x8DCT ( left_type [ LTOP ] ) ) {
nnz_cache [ 3 + 8 * 1 ] =
nnz_cache [ 3 + 8 * 2 ] = ( h - > cbp_table [ left_xy [ LTOP ] ] & 0x2000 ) > > 12 ; // FIXME check MBAFF
}
if ( IS_8x8DCT ( left_type [ LBOT ] ) ) {
nnz_cache [ 3 + 8 * 3 ] =
nnz_cache [ 3 + 8 * 4 ] = ( h - > cbp_table [ left_xy [ LBOT ] ] & 0x8000 ) > > 12 ; // FIXME check MBAFF
}
if ( IS_8x8DCT ( mb_type ) ) {
nnz_cache [ scan8 [ 0 ] ] =
nnz_cache [ scan8 [ 1 ] ] =
nnz_cache [ scan8 [ 2 ] ] =
2015-01-17 23:28:46 +02:00
nnz_cache [ scan8 [ 3 ] ] = ( sl - > cbp & 0x1000 ) > > 12 ;
2014-03-19 18:52:47 +03:00
nnz_cache [ scan8 [ 0 + 4 ] ] =
nnz_cache [ scan8 [ 1 + 4 ] ] =
nnz_cache [ scan8 [ 2 + 4 ] ] =
2015-01-17 23:28:46 +02:00
nnz_cache [ scan8 [ 3 + 4 ] ] = ( sl - > cbp & 0x2000 ) > > 12 ;
2014-03-19 18:52:47 +03:00
nnz_cache [ scan8 [ 0 + 8 ] ] =
nnz_cache [ scan8 [ 1 + 8 ] ] =
nnz_cache [ scan8 [ 2 + 8 ] ] =
2015-01-17 23:28:46 +02:00
nnz_cache [ scan8 [ 3 + 8 ] ] = ( sl - > cbp & 0x4000 ) > > 12 ;
2014-03-19 18:52:47 +03:00
nnz_cache [ scan8 [ 0 + 12 ] ] =
nnz_cache [ scan8 [ 1 + 12 ] ] =
nnz_cache [ scan8 [ 2 + 12 ] ] =
2015-01-17 23:28:46 +02:00
nnz_cache [ scan8 [ 3 + 12 ] ] = ( sl - > cbp & 0x8000 ) > > 12 ;
2014-03-19 18:52:47 +03:00
}
}
return 0 ;
}
2015-01-28 14:24:32 +02:00
static void loop_filter ( const H264Context * h , H264SliceContext * sl , int start_x , int end_x )
2014-03-19 18:52:47 +03:00
{
uint8_t * dest_y , * dest_cb , * dest_cr ;
int linesize , uvlinesize , mb_x , mb_y ;
2015-01-17 23:28:46 +02:00
const int end_mb_y = sl - > mb_y + FRAME_MBAFF ( h ) ;
2015-01-17 23:28:46 +02:00
const int old_slice_type = sl - > slice_type ;
2014-03-19 18:52:47 +03:00
const int pixel_shift = h - > pixel_shift ;
const int block_h = 16 > > h - > chroma_y_shift ;
2016-04-13 13:52:36 +02:00
if ( h - > postpone_filter )
return ;
2015-01-17 23:28:46 +02:00
if ( sl - > deblocking_filter ) {
2014-03-19 18:52:47 +03:00
for ( mb_x = start_x ; mb_x < end_x ; mb_x + + )
for ( mb_y = end_mb_y - FRAME_MBAFF ( h ) ; mb_y < = end_mb_y ; mb_y + + ) {
int mb_xy , mb_type ;
2015-01-17 23:28:46 +02:00
mb_xy = sl - > mb_xy = mb_x + mb_y * h - > mb_stride ;
2014-03-19 18:52:47 +03:00
mb_type = h - > cur_pic . mb_type [ mb_xy ] ;
if ( FRAME_MBAFF ( h ) )
2015-01-17 23:28:46 +02:00
sl - > mb_mbaff =
2015-01-17 23:28:46 +02:00
sl - > mb_field_decoding_flag = ! ! IS_INTERLACED ( mb_type ) ;
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
sl - > mb_x = mb_x ;
sl - > mb_y = mb_y ;
2015-04-17 12:09:50 +02:00
dest_y = h - > cur_pic . f - > data [ 0 ] +
2015-01-29 14:06:25 +02:00
( ( mb_x < < pixel_shift ) + mb_y * sl - > linesize ) * 16 ;
2015-04-17 12:09:50 +02:00
dest_cb = h - > cur_pic . f - > data [ 1 ] +
2014-03-19 18:52:47 +03:00
( mb_x < < pixel_shift ) * ( 8 < < CHROMA444 ( h ) ) +
2015-01-29 14:06:25 +02:00
mb_y * sl - > uvlinesize * block_h ;
2015-04-17 12:09:50 +02:00
dest_cr = h - > cur_pic . f - > data [ 2 ] +
2014-03-19 18:52:47 +03:00
( mb_x < < pixel_shift ) * ( 8 < < CHROMA444 ( h ) ) +
2015-01-29 14:06:25 +02:00
mb_y * sl - > uvlinesize * block_h ;
2014-03-19 18:52:47 +03:00
// FIXME simplify above
2015-01-17 23:28:46 +02:00
if ( MB_FIELD ( sl ) ) {
2015-01-29 14:06:25 +02:00
linesize = sl - > mb_linesize = sl - > linesize * 2 ;
uvlinesize = sl - > mb_uvlinesize = sl - > uvlinesize * 2 ;
2014-03-19 18:52:47 +03:00
if ( mb_y & 1 ) { // FIXME move out of this function?
2015-01-29 14:06:25 +02:00
dest_y - = sl - > linesize * 15 ;
dest_cb - = sl - > uvlinesize * ( block_h - 1 ) ;
dest_cr - = sl - > uvlinesize * ( block_h - 1 ) ;
2014-03-19 18:52:47 +03:00
}
} else {
2015-01-29 14:06:25 +02:00
linesize = sl - > mb_linesize = sl - > linesize ;
uvlinesize = sl - > mb_uvlinesize = sl - > uvlinesize ;
2014-03-19 18:52:47 +03:00
}
2015-01-17 23:28:46 +02:00
backup_mb_border ( h , sl , dest_y , dest_cb , dest_cr , linesize ,
2014-03-19 18:52:47 +03:00
uvlinesize , 0 ) ;
2015-01-17 23:28:46 +02:00
if ( fill_filter_caches ( h , sl , mb_type ) )
2014-03-19 18:52:47 +03:00
continue ;
2016-05-12 14:25:52 +02:00
sl - > chroma_qp [ 0 ] = get_chroma_qp ( h - > ps . pps , 0 , h - > cur_pic . qscale_table [ mb_xy ] ) ;
sl - > chroma_qp [ 1 ] = get_chroma_qp ( h - > ps . pps , 1 , h - > cur_pic . qscale_table [ mb_xy ] ) ;
2014-03-19 18:52:47 +03:00
if ( FRAME_MBAFF ( h ) ) {
2015-01-17 23:28:46 +02:00
ff_h264_filter_mb ( h , sl , mb_x , mb_y , dest_y , dest_cb , dest_cr ,
2014-03-19 18:52:47 +03:00
linesize , uvlinesize ) ;
} else {
2015-01-17 23:28:46 +02:00
ff_h264_filter_mb_fast ( h , sl , mb_x , mb_y , dest_y , dest_cb ,
2014-03-19 18:52:47 +03:00
dest_cr , linesize , uvlinesize ) ;
}
}
}
2015-01-17 23:28:46 +02:00
sl - > slice_type = old_slice_type ;
2015-01-17 23:28:46 +02:00
sl - > mb_x = end_x ;
sl - > mb_y = end_mb_y - FRAME_MBAFF ( h ) ;
2016-05-12 14:25:52 +02:00
sl - > chroma_qp [ 0 ] = get_chroma_qp ( h - > ps . pps , 0 , sl - > qscale ) ;
sl - > chroma_qp [ 1 ] = get_chroma_qp ( h - > ps . pps , 1 , sl - > qscale ) ;
2014-03-19 18:52:47 +03:00
}
2015-01-28 14:24:32 +02:00
static void predict_field_decoding_flag ( const H264Context * h , H264SliceContext * sl )
2014-03-19 18:52:47 +03:00
{
2015-01-17 23:28:46 +02:00
const int mb_xy = sl - > mb_x + sl - > mb_y * h - > mb_stride ;
2015-01-17 23:28:46 +02:00
int mb_type = ( h - > slice_table [ mb_xy - 1 ] = = sl - > slice_num ) ?
2014-03-19 18:52:47 +03:00
h - > cur_pic . mb_type [ mb_xy - 1 ] :
2015-01-17 23:28:46 +02:00
( h - > slice_table [ mb_xy - h - > mb_stride ] = = sl - > slice_num ) ?
2014-03-19 18:52:47 +03:00
h - > cur_pic . mb_type [ mb_xy - h - > mb_stride ] : 0 ;
2015-01-17 23:28:46 +02:00
sl - > mb_mbaff = sl - > mb_field_decoding_flag = IS_INTERLACED ( mb_type ) ? 1 : 0 ;
2014-03-19 18:52:47 +03:00
}
/**
* Draw edges and report progress for the last MB row .
*/
2015-01-28 14:24:32 +02:00
static void decode_finish_row ( const H264Context * h , H264SliceContext * sl )
2014-03-19 18:52:47 +03:00
{
2015-01-17 23:28:46 +02:00
int top = 16 * ( sl - > mb_y > > FIELD_PICTURE ( h ) ) ;
2014-03-19 18:52:47 +03:00
int pic_height = 16 * h - > mb_height > > FIELD_PICTURE ( h ) ;
int height = 16 < < FRAME_MBAFF ( h ) ;
int deblock_border = ( 16 + 4 ) < < FRAME_MBAFF ( h ) ;
2015-01-17 23:28:46 +02:00
if ( sl - > deblocking_filter ) {
2014-03-19 18:52:47 +03:00
if ( ( top + height ) > = pic_height )
height + = deblock_border ;
top - = deblock_border ;
}
if ( top > = pic_height | | ( top + height ) < 0 )
return ;
height = FFMIN ( height , pic_height - top ) ;
if ( top < 0 ) {
height = top + height ;
top = 0 ;
}
2015-01-17 23:28:46 +02:00
ff_h264_draw_horiz_band ( h , sl , top , height ) ;
2014-03-19 18:52:47 +03:00
2015-04-04 12:36:43 +02:00
if ( h - > droppable | | sl - > h264 - > slice_ctx [ 0 ] . er . error_occurred )
2014-03-19 18:52:47 +03:00
return ;
ff_thread_report_progress ( & h - > cur_pic_ptr - > tf , top + height - 1 ,
h - > picture_structure = = PICT_BOTTOM_FIELD ) ;
}
2015-01-17 23:28:46 +02:00
static void er_add_slice ( H264SliceContext * sl ,
2015-01-17 23:28:46 +02:00
int startx , int starty ,
2014-03-19 18:52:47 +03:00
int endx , int endy , int status )
{
2015-03-31 10:35:15 +02:00
if ( ! sl - > h264 - > enable_er )
return ;
2014-03-24 03:24:55 +03:00
if ( CONFIG_ERROR_RESILIENCE ) {
2015-04-04 12:36:43 +02:00
ERContext * er = & sl - > h264 - > slice_ctx [ 0 ] . er ;
2014-03-19 18:52:47 +03:00
2014-03-24 03:24:55 +03:00
ff_er_add_slice ( er , startx , starty , endx , endy , status ) ;
}
2014-03-19 18:52:47 +03:00
}
static int decode_slice ( struct AVCodecContext * avctx , void * arg )
{
2015-01-17 19:45:29 +02:00
H264SliceContext * sl = arg ;
2015-01-28 14:24:32 +02:00
const H264Context * h = sl - > h264 ;
2015-01-17 23:28:46 +02:00
int lf_x_start = sl - > mb_x ;
2016-04-13 13:52:36 +02:00
int orig_deblock = sl - > deblocking_filter ;
2015-01-17 23:28:46 +02:00
int ret ;
2015-04-17 12:09:50 +02:00
sl - > linesize = h - > cur_pic_ptr - > f - > linesize [ 0 ] ;
sl - > uvlinesize = h - > cur_pic_ptr - > f - > linesize [ 1 ] ;
2015-01-29 14:06:25 +02:00
ret = alloc_scratch_buffers ( sl , sl - > linesize ) ;
2015-01-17 23:28:46 +02:00
if ( ret < 0 )
return ret ;
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
sl - > mb_skip_run = - 1 ;
2014-03-19 18:52:47 +03:00
2015-03-22 00:16:36 +02:00
av_assert0 ( h - > block_offset [ 15 ] = = ( 4 * ( ( scan8 [ 15 ] - scan8 [ 0 ] ) & 7 ) < < h - > pixel_shift ) + 4 * sl - > linesize * ( ( scan8 [ 15 ] - scan8 [ 0 ] ) > > 3 ) ) ;
2014-03-24 03:24:55 +03:00
2016-04-13 13:52:36 +02:00
if ( h - > postpone_filter )
sl - > deblocking_filter = 0 ;
2015-01-17 23:28:46 +02:00
sl - > is_complex = FRAME_MBAFF ( h ) | | h - > picture_structure ! = PICT_FRAME | |
avctx - > codec_id ! = AV_CODEC_ID_H264 | |
2015-06-29 21:59:37 +02:00
( CONFIG_GRAY & & ( h - > flags & AV_CODEC_FLAG_GRAY ) ) ;
2014-03-19 18:52:47 +03:00
2015-04-04 12:36:43 +02:00
if ( ! ( h - > avctx - > active_thread_type & FF_THREAD_SLICE ) & & h - > picture_structure = = PICT_FRAME & & h - > slice_ctx [ 0 ] . er . error_status_table ) {
2015-03-21 17:54:48 +02:00
const int start_i = av_clip ( sl - > resync_mb_x + sl - > resync_mb_y * h - > mb_width , 0 , h - > mb_num - 1 ) ;
2014-03-24 03:24:55 +03:00
if ( start_i ) {
2015-04-04 12:36:43 +02:00
int prev_status = h - > slice_ctx [ 0 ] . er . error_status_table [ h - > slice_ctx [ 0 ] . er . mb_index2xy [ start_i - 1 ] ] ;
2014-03-24 03:24:55 +03:00
prev_status & = ~ VP_START ;
if ( prev_status ! = ( ER_MV_END | ER_DC_END | ER_AC_END ) )
2015-04-04 12:36:43 +02:00
h - > slice_ctx [ 0 ] . er . error_occurred = 1 ;
2014-03-24 03:24:55 +03:00
}
}
2016-03-22 14:31:21 +02:00
if ( h - > ps . pps - > cabac ) {
2014-03-19 18:52:47 +03:00
/* realign */
2015-01-27 15:39:06 +02:00
align_get_bits ( & sl - > gb ) ;
2014-03-19 18:52:47 +03:00
/* init cabac */
2015-11-27 14:37:50 +02:00
ret = ff_init_cabac_decoder ( & sl - > cabac ,
2015-01-27 15:39:06 +02:00
sl - > gb . buffer + get_bits_count ( & sl - > gb ) / 8 ,
( get_bits_left ( & sl - > gb ) + 7 ) / 8 ) ;
2015-11-27 14:37:50 +02:00
if ( ret < 0 )
return ret ;
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
ff_h264_init_cabac_states ( h , sl ) ;
2014-03-19 18:52:47 +03:00
for ( ; ; ) {
// START_TIMER
2015-04-07 00:40:21 +02:00
int ret , eos ;
2015-05-06 11:12:55 +02:00
if ( sl - > mb_x + sl - > mb_y * h - > mb_width > = sl - > next_slice_idx ) {
av_log ( h - > avctx , AV_LOG_ERROR , " Slice overlaps with next at %d \n " ,
sl - > next_slice_idx ) ;
2015-04-07 00:40:21 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x ,
sl - > mb_y , ER_MB_ERROR ) ;
return AVERROR_INVALIDDATA ;
}
ret = ff_h264_decode_mb_cabac ( h , sl ) ;
2014-03-19 18:52:47 +03:00
// STOP_TIMER("decode_mb_cabac")
if ( ret > = 0 )
2015-01-17 19:45:29 +02:00
ff_h264_hl_decode_mb ( h , sl ) ;
2014-03-19 18:52:47 +03:00
// FIXME optimal? or let mb_decode decode 16x32 ?
if ( ret > = 0 & & FRAME_MBAFF ( h ) ) {
2015-01-17 23:28:46 +02:00
sl - > mb_y + + ;
2014-03-19 18:52:47 +03:00
2015-01-17 23:28:46 +02:00
ret = ff_h264_decode_mb_cabac ( h , sl ) ;
2014-03-19 18:52:47 +03:00
if ( ret > = 0 )
2015-01-17 19:45:29 +02:00
ff_h264_hl_decode_mb ( h , sl ) ;
2015-01-17 23:28:46 +02:00
sl - > mb_y - - ;
2014-03-19 18:52:47 +03:00
}
2015-01-17 23:28:46 +02:00
eos = get_cabac_terminate ( & sl - > cabac ) ;
2014-03-19 18:52:47 +03:00
if ( ( h - > workaround_bugs & FF_BUG_TRUNCATED ) & &
2015-01-17 23:28:46 +02:00
sl - > cabac . bytestream > sl - > cabac . bytestream_end + 2 ) {
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x - 1 ,
2015-01-17 23:28:46 +02:00
sl - > mb_y , ER_MB_END ) ;
if ( sl - > mb_x > = lf_x_start )
loop_filter ( h , sl , lf_x_start , sl - > mb_x + 1 ) ;
2016-04-13 13:52:36 +02:00
goto finish ;
2014-03-19 18:52:47 +03:00
}
2015-03-21 16:45:44 +02:00
if ( sl - > cabac . bytestream > sl - > cabac . bytestream_end + 2 )
av_log ( h - > avctx , AV_LOG_DEBUG , " bytestream overread % " PTRDIFF_SPECIFIER " \n " , sl - > cabac . bytestream_end - sl - > cabac . bytestream ) ;
if ( ret < 0 | | sl - > cabac . bytestream > sl - > cabac . bytestream_end + 4 ) {
2014-03-19 18:52:47 +03:00
av_log ( h - > avctx , AV_LOG_ERROR ,
2014-04-24 19:01:30 +03:00
" error while decoding MB %d %d, bytestream % " PTRDIFF_SPECIFIER " \n " ,
2015-01-17 23:28:46 +02:00
sl - > mb_x , sl - > mb_y ,
2015-01-17 23:28:46 +02:00
sl - > cabac . bytestream_end - sl - > cabac . bytestream ) ;
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x ,
2015-01-17 23:28:46 +02:00
sl - > mb_y , ER_MB_ERROR ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
2015-01-17 23:28:46 +02:00
if ( + + sl - > mb_x > = h - > mb_width ) {
loop_filter ( h , sl , lf_x_start , sl - > mb_x ) ;
sl - > mb_x = lf_x_start = 0 ;
2015-01-17 23:28:46 +02:00
decode_finish_row ( h , sl ) ;
2015-01-17 23:28:46 +02:00
+ + sl - > mb_y ;
2014-03-19 18:52:47 +03:00
if ( FIELD_OR_MBAFF_PICTURE ( h ) ) {
2015-01-17 23:28:46 +02:00
+ + sl - > mb_y ;
if ( FRAME_MBAFF ( h ) & & sl - > mb_y < h - > mb_height )
2015-01-17 23:28:46 +02:00
predict_field_decoding_flag ( h , sl ) ;
2014-03-19 18:52:47 +03:00
}
}
2015-01-17 23:28:46 +02:00
if ( eos | | sl - > mb_y > = h - > mb_height ) {
2015-03-16 10:57:36 +02:00
ff_tlog ( h - > avctx , " slice end %d %d \n " ,
2015-01-27 15:39:06 +02:00
get_bits_count ( & sl - > gb ) , sl - > gb . size_in_bits ) ;
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x - 1 ,
2015-01-17 23:28:46 +02:00
sl - > mb_y , ER_MB_END ) ;
if ( sl - > mb_x > lf_x_start )
loop_filter ( h , sl , lf_x_start , sl - > mb_x ) ;
2016-04-13 13:52:36 +02:00
goto finish ;
2014-03-19 18:52:47 +03:00
}
}
} else {
for ( ; ; ) {
2015-04-07 00:40:21 +02:00
int ret ;
2015-05-06 11:12:55 +02:00
if ( sl - > mb_x + sl - > mb_y * h - > mb_width > = sl - > next_slice_idx ) {
av_log ( h - > avctx , AV_LOG_ERROR , " Slice overlaps with next at %d \n " ,
sl - > next_slice_idx ) ;
2015-04-07 00:40:21 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x ,
sl - > mb_y , ER_MB_ERROR ) ;
return AVERROR_INVALIDDATA ;
}
ret = ff_h264_decode_mb_cavlc ( h , sl ) ;
2014-03-19 18:52:47 +03:00
if ( ret > = 0 )
2015-01-17 19:45:29 +02:00
ff_h264_hl_decode_mb ( h , sl ) ;
2014-03-19 18:52:47 +03:00
// FIXME optimal? or let mb_decode decode 16x32 ?
if ( ret > = 0 & & FRAME_MBAFF ( h ) ) {
2015-01-17 23:28:46 +02:00
sl - > mb_y + + ;
2015-01-17 23:28:46 +02:00
ret = ff_h264_decode_mb_cavlc ( h , sl ) ;
2014-03-19 18:52:47 +03:00
if ( ret > = 0 )
2015-01-17 19:45:29 +02:00
ff_h264_hl_decode_mb ( h , sl ) ;
2015-01-17 23:28:46 +02:00
sl - > mb_y - - ;
2014-03-19 18:52:47 +03:00
}
if ( ret < 0 ) {
av_log ( h - > avctx , AV_LOG_ERROR ,
2015-01-17 23:28:46 +02:00
" error while decoding MB %d %d \n " , sl - > mb_x , sl - > mb_y ) ;
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x ,
2015-01-17 23:28:46 +02:00
sl - > mb_y , ER_MB_ERROR ) ;
2014-03-19 18:52:47 +03:00
return ret ;
}
2015-01-17 23:28:46 +02:00
if ( + + sl - > mb_x > = h - > mb_width ) {
loop_filter ( h , sl , lf_x_start , sl - > mb_x ) ;
sl - > mb_x = lf_x_start = 0 ;
2015-01-17 23:28:46 +02:00
decode_finish_row ( h , sl ) ;
2015-01-17 23:28:46 +02:00
+ + sl - > mb_y ;
2014-03-19 18:52:47 +03:00
if ( FIELD_OR_MBAFF_PICTURE ( h ) ) {
2015-01-17 23:28:46 +02:00
+ + sl - > mb_y ;
if ( FRAME_MBAFF ( h ) & & sl - > mb_y < h - > mb_height )
2015-01-17 23:28:46 +02:00
predict_field_decoding_flag ( h , sl ) ;
2014-03-19 18:52:47 +03:00
}
2015-01-17 23:28:46 +02:00
if ( sl - > mb_y > = h - > mb_height ) {
2015-03-16 10:57:36 +02:00
ff_tlog ( h - > avctx , " slice end %d %d \n " ,
2015-01-27 15:39:06 +02:00
get_bits_count ( & sl - > gb ) , sl - > gb . size_in_bits ) ;
2014-03-19 18:52:47 +03:00
2015-03-21 18:13:24 +02:00
if ( get_bits_left ( & sl - > gb ) = = 0
| | get_bits_left ( & sl - > gb ) > 0 & & ! ( h - > avctx - > err_recognition & AV_EF_AGGRESSIVE ) ) {
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y ,
2015-01-17 23:28:46 +02:00
sl - > mb_x - 1 , sl - > mb_y , ER_MB_END ) ;
2014-03-19 18:52:47 +03:00
2016-04-13 13:52:36 +02:00
goto finish ;
2014-03-19 18:52:47 +03:00
} else {
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y ,
2015-03-21 17:25:04 +02:00
sl - > mb_x , sl - > mb_y , ER_MB_END ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
}
}
2015-01-27 15:39:06 +02:00
if ( get_bits_left ( & sl - > gb ) < = 0 & & sl - > mb_skip_run < = 0 ) {
2015-03-16 10:57:36 +02:00
ff_tlog ( h - > avctx , " slice end %d %d \n " ,
2015-01-27 15:39:06 +02:00
get_bits_count ( & sl - > gb ) , sl - > gb . size_in_bits ) ;
2014-03-19 18:52:47 +03:00
2015-01-27 15:39:06 +02:00
if ( get_bits_left ( & sl - > gb ) = = 0 ) {
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y ,
2015-01-17 23:28:46 +02:00
sl - > mb_x - 1 , sl - > mb_y , ER_MB_END ) ;
if ( sl - > mb_x > lf_x_start )
loop_filter ( h , sl , lf_x_start , sl - > mb_x ) ;
2014-03-19 18:52:47 +03:00
2016-04-13 13:52:36 +02:00
goto finish ;
2014-03-19 18:52:47 +03:00
} else {
2015-01-17 23:28:46 +02:00
er_add_slice ( sl , sl - > resync_mb_x , sl - > resync_mb_y , sl - > mb_x ,
2015-01-17 23:28:46 +02:00
sl - > mb_y , ER_MB_ERROR ) ;
2014-03-19 18:52:47 +03:00
return AVERROR_INVALIDDATA ;
}
}
}
}
2016-04-13 13:52:36 +02:00
finish :
sl - > deblocking_filter = orig_deblock ;
return 0 ;
2014-03-19 18:52:47 +03:00
}
/**
* Call decode_slice ( ) for each context .
*
* @ param h h264 master context
* @ param context_count number of contexts to execute
*/
int ff_h264_execute_decode_slices ( H264Context * h , unsigned context_count )
{
AVCodecContext * const avctx = h - > avctx ;
2015-01-17 23:28:46 +02:00
H264SliceContext * sl ;
2015-05-06 11:12:55 +02:00
int i , j ;
2014-03-19 18:52:47 +03:00
2015-03-21 17:25:04 +02:00
av_assert0 ( context_count & & h - > slice_ctx [ context_count - 1 ] . mb_y < h - > mb_height ) ;
2014-03-19 18:52:47 +03:00
2015-06-27 18:38:17 +02:00
h - > slice_ctx [ 0 ] . next_slice_idx = INT_MAX ;
2015-04-07 00:40:21 +02:00
2015-08-17 01:35:59 +02:00
if ( h - > avctx - > hwaccel
# if FF_API_CAP_VDPAU
| | h - > avctx - > codec - > capabilities & AV_CODEC_CAP_HWACCEL_VDPAU
# endif
)
2014-03-19 18:52:47 +03:00
return 0 ;
if ( context_count = = 1 ) {
2015-05-06 11:12:55 +02:00
int ret ;
h - > slice_ctx [ 0 ] . next_slice_idx = h - > mb_width * h - > mb_height ;
2016-04-13 13:52:36 +02:00
h - > postpone_filter = 0 ;
2015-05-06 11:12:55 +02:00
ret = decode_slice ( avctx , & h - > slice_ctx [ 0 ] ) ;
2015-01-17 23:28:46 +02:00
h - > mb_y = h - > slice_ctx [ 0 ] . mb_y ;
return ret ;
2014-03-19 18:52:47 +03:00
} else {
2014-03-24 03:24:55 +03:00
av_assert0 ( context_count > 0 ) ;
2015-04-07 00:40:21 +02:00
for ( i = 0 ; i < context_count ; i + + ) {
2015-05-06 11:12:55 +02:00
int next_slice_idx = h - > mb_width * h - > mb_height ;
int slice_idx ;
2015-01-17 23:28:46 +02:00
sl = & h - > slice_ctx [ i ] ;
2014-03-24 03:24:55 +03:00
if ( CONFIG_ERROR_RESILIENCE ) {
2015-03-21 21:00:34 +02:00
sl - > er . error_count = 0 ;
2014-03-24 03:24:55 +03:00
}
2015-05-06 11:12:55 +02:00
/* make sure none of those slices overlap */
slice_idx = sl - > mb_y * h - > mb_width + sl - > mb_x ;
2015-04-07 00:40:21 +02:00
for ( j = 0 ; j < context_count ; j + + ) {
H264SliceContext * sl2 = & h - > slice_ctx [ j ] ;
2015-05-06 11:12:55 +02:00
int slice_idx2 = sl2 - > mb_y * h - > mb_width + sl2 - > mb_x ;
2015-04-07 00:40:21 +02:00
2015-05-06 11:12:55 +02:00
if ( i = = j | | slice_idx2 < slice_idx )
2015-04-07 00:40:21 +02:00
continue ;
2015-05-06 11:12:55 +02:00
next_slice_idx = FFMIN ( next_slice_idx , slice_idx2 ) ;
2015-04-07 00:40:21 +02:00
}
2015-05-06 11:12:55 +02:00
sl - > next_slice_idx = next_slice_idx ;
2014-03-19 18:52:47 +03:00
}
2015-01-17 19:45:29 +02:00
avctx - > execute ( avctx , decode_slice , h - > slice_ctx ,
NULL , context_count , sizeof ( h - > slice_ctx [ 0 ] ) ) ;
2014-03-19 18:52:47 +03:00
/* pull back stuff from slices to master context */
2015-01-17 23:28:46 +02:00
sl = & h - > slice_ctx [ context_count - 1 ] ;
h - > mb_y = sl - > mb_y ;
2014-03-24 03:24:55 +03:00
if ( CONFIG_ERROR_RESILIENCE ) {
for ( i = 1 ; i < context_count ; i + + )
2015-03-21 21:00:34 +02:00
h - > slice_ctx [ 0 ] . er . error_count + = h - > slice_ctx [ i ] . er . error_count ;
2014-03-24 03:24:55 +03:00
}
2016-04-13 13:52:36 +02:00
if ( h - > postpone_filter ) {
h - > postpone_filter = 0 ;
for ( i = 0 ; i < context_count ; i + + ) {
int y_end , x_end ;
sl = & h - > slice_ctx [ i ] ;
y_end = FFMIN ( sl - > mb_y + 1 , h - > mb_height ) ;
x_end = ( sl - > mb_y > = h - > mb_height ) ? h - > mb_width : sl - > mb_x ;
for ( j = sl - > resync_mb_y ; j < y_end ; j + = 1 + FIELD_OR_MBAFF_PICTURE ( h ) ) {
sl - > mb_y = j ;
loop_filter ( h , sl , j > sl - > resync_mb_y ? 0 : sl - > resync_mb_x ,
j = = y_end - 1 ? x_end : h - > mb_width ) ;
}
}
}
2014-03-19 18:52:47 +03:00
}
return 0 ;
}