@@ -1317,6 +1317,7 @@ struct CvVideoWriter_FFMPEG
1317
1317
AVStream * video_st;
1318
1318
int input_pix_fmt;
1319
1319
unsigned char * aligned_input;
1320
+ size_t aligned_input_size;
1320
1321
int frame_width, frame_height;
1321
1322
int frame_idx;
1322
1323
bool ok;
@@ -1394,6 +1395,7 @@ void CvVideoWriter_FFMPEG::init()
1394
1395
video_st = 0 ;
1395
1396
input_pix_fmt = 0 ;
1396
1397
aligned_input = NULL ;
1398
+ aligned_input_size = 0 ;
1397
1399
img_convert_ctx = 0 ;
1398
1400
frame_width = frame_height = 0 ;
1399
1401
frame_idx = 0 ;
@@ -1702,17 +1704,28 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
1702
1704
#endif
1703
1705
1704
1706
// FFmpeg contains SIMD optimizations which can sometimes read data past
1705
- // the supplied input buffer. To ensure that doesn't happen, we pad the
1706
- // step to a multiple of 32 (that's the minimal alignment for which Valgrind
1707
- // doesn't raise any warnings).
1708
- const int STEP_ALIGNMENT = 32 ;
1709
- if ( step % STEP_ALIGNMENT != 0 )
1707
+ // the supplied input buffer.
1708
+ // Related info: https://trac.ffmpeg.org/ticket/6763
1709
+ // 1. To ensure that doesn't happen, we pad the step to a multiple of 32
1710
+ // (that's the minimal alignment for which Valgrind doesn't raise any warnings).
1711
+ // 2. (dataend - SIMD_SIZE) and (dataend + SIMD_SIZE) is from the same 4k page
1712
+ const int CV_STEP_ALIGNMENT = 32 ;
1713
+ const size_t CV_SIMD_SIZE = 32 ;
1714
+ const size_t CV_PAGE_MASK = ~(4096 - 1 );
1715
+ const uchar* dataend = data + ((size_t )height * step);
1716
+ if (step % CV_STEP_ALIGNMENT != 0 ||
1717
+ (((size_t )dataend - CV_SIMD_SIZE) & CV_PAGE_MASK) != (((size_t )dataend + CV_SIMD_SIZE) & CV_PAGE_MASK))
1710
1718
{
1711
- int aligned_step = (step + STEP_ALIGNMENT - 1 ) & -STEP_ALIGNMENT ;
1719
+ int aligned_step = (step + CV_STEP_ALIGNMENT - 1 ) & ~(CV_STEP_ALIGNMENT - 1 ) ;
1712
1720
1713
- if ( !aligned_input )
1721
+ size_t new_size = (aligned_step * height + CV_SIMD_SIZE);
1722
+
1723
+ if (!aligned_input || aligned_input_size < new_size)
1714
1724
{
1715
- aligned_input = (unsigned char *)av_mallocz (aligned_step * height);
1725
+ if (aligned_input)
1726
+ av_freep (&aligned_input);
1727
+ aligned_input_size = new_size;
1728
+ aligned_input = (unsigned char *)av_mallocz (aligned_input_size);
1716
1729
}
1717
1730
1718
1731
if (origin == 1 )
0 commit comments