Commit da669569 authored by Alexander Smorkalov's avatar Alexander Smorkalov

Merge pull request #6281 from SpecLad:videowriter-oob

parents d142c05d eb40afa2
...@@ -1229,7 +1229,7 @@ struct CvVideoWriter_FFMPEG ...@@ -1229,7 +1229,7 @@ struct CvVideoWriter_FFMPEG
uint8_t * picbuf; uint8_t * picbuf;
AVStream * video_st; AVStream * video_st;
int input_pix_fmt; int input_pix_fmt;
Image_FFMPEG temp_image; unsigned char * aligned_input;
int frame_width, frame_height; int frame_width, frame_height;
int frame_idx; int frame_idx;
bool ok; bool ok;
...@@ -1306,7 +1306,7 @@ void CvVideoWriter_FFMPEG::init() ...@@ -1306,7 +1306,7 @@ void CvVideoWriter_FFMPEG::init()
picbuf = 0; picbuf = 0;
video_st = 0; video_st = 0;
input_pix_fmt = 0; input_pix_fmt = 0;
memset(&temp_image, 0, sizeof(temp_image)); aligned_input = NULL;
img_convert_ctx = 0; img_convert_ctx = 0;
frame_width = frame_height = 0; frame_width = frame_height = 0;
frame_idx = 0; frame_idx = 0;
...@@ -1552,7 +1552,20 @@ static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, ...@@ -1552,7 +1552,20 @@ static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st,
/// write a frame with FFMPEG /// write a frame with FFMPEG
bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin ) bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )
{ {
bool ret = false; // check parameters
if (input_pix_fmt == AV_PIX_FMT_BGR24) {
if (cn != 3) {
return false;
}
}
else if (input_pix_fmt == AV_PIX_FMT_GRAY8) {
if (cn != 1) {
return false;
}
}
else {
assert(false);
}
if( (width & -2) != frame_width || (height & -2) != frame_height || !data ) if( (width & -2) != frame_width || (height & -2) != frame_height || !data )
return false; return false;
...@@ -1566,58 +1579,29 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1566,58 +1579,29 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
AVCodecContext *c = &(video_st->codec); AVCodecContext *c = &(video_st->codec);
#endif #endif
#if LIBAVFORMAT_BUILD < 5231 // FFmpeg contains SIMD optimizations which can sometimes read data past
// It is not needed in the latest versions of the ffmpeg // the supplied input buffer. To ensure that doesn't happen, we pad the
if( c->codec_id == CV_CODEC(CODEC_ID_RAWVIDEO) && origin != 1 ) // step to a multiple of 32 (that's the minimal alignment for which Valgrind
{ // doesn't raise any warnings).
if( !temp_image.data ) const int STEP_ALIGNMENT = 32;
{ if( step % STEP_ALIGNMENT != 0 )
temp_image.step = (width*cn + 3) & -4;
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
}
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn);
data = temp_image.data;
step = temp_image.step;
}
#else
if( width*cn != step )
{ {
if( !temp_image.data ) int aligned_step = (step + STEP_ALIGNMENT - 1) & -STEP_ALIGNMENT;
if( !aligned_input )
{ {
temp_image.step = width*cn; aligned_input = (unsigned char*)av_mallocz(aligned_step * height);
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
} }
if (origin == 1) if (origin == 1)
for( int y = 0; y < height; y++ ) for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step); memcpy(aligned_input + y*aligned_step, data + (height-1-y)*step, step);
else else
for( int y = 0; y < height; y++ ) for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step); memcpy(aligned_input + y*aligned_step, data + y*step, step);
data = temp_image.data;
step = temp_image.step;
}
#endif
// check parameters data = aligned_input;
if (input_pix_fmt == AV_PIX_FMT_BGR24) { step = aligned_step;
if (cn != 3) {
return false;
}
}
else if (input_pix_fmt == AV_PIX_FMT_GRAY8) {
if (cn != 1) {
return false;
}
}
else {
assert(false);
} }
if ( c->pix_fmt != input_pix_fmt ) { if ( c->pix_fmt != input_pix_fmt ) {
...@@ -1625,6 +1609,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1625,6 +1609,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
// let input_picture point to the raw data buffer of 'image' // let input_picture point to the raw data buffer of 'image'
avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, avpicture_fill((AVPicture *)input_picture, (uint8_t *) data,
(AVPixelFormat)input_pix_fmt, width, height); (AVPixelFormat)input_pix_fmt, width, height);
input_picture->linesize[0] = step;
if( !img_convert_ctx ) if( !img_convert_ctx )
{ {
...@@ -1649,10 +1634,11 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1649,10 +1634,11 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
else{ else{
avpicture_fill((AVPicture *)picture, (uint8_t *) data, avpicture_fill((AVPicture *)picture, (uint8_t *) data,
(AVPixelFormat)input_pix_fmt, width, height); (AVPixelFormat)input_pix_fmt, width, height);
picture->linesize[0] = step;
} }
picture->pts = frame_idx; picture->pts = frame_idx;
ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; bool ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
frame_idx++; frame_idx++;
return ret; return ret;
...@@ -1735,11 +1721,7 @@ void CvVideoWriter_FFMPEG::close() ...@@ -1735,11 +1721,7 @@ void CvVideoWriter_FFMPEG::close()
/* free the stream */ /* free the stream */
avformat_free_context(oc); avformat_free_context(oc);
if( temp_image.data ) av_freep(&aligned_input);
{
free(temp_image.data);
temp_image.data = 0;
}
init(); init();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment