I know there are similar questions to this one but I can't seem to find the solution in my own circumstances.
I've made a program using opengl and ffmpeg that uses a buffer to complete it's operations. Normally, the program runs just fine with no errors whatsoever. However when I run my application using valgrind I get this error:
==31277== Invalid read of size 16
==31277== at 0xD27852: memcpy (string_fortified.h:29)
==31277== by 0xD27852: scale_internal (swscale.c:947)
==31277== by 0xD29EE8: sws_scale (swscale.c:1213)
==31277== by 0x268BBC: Videooio::video_encoder::set_frame_yuv_from_rgb(AVFrame*, SwsContext*) (video_encoder.cpp:441)
==31277== by 0x268D18: Videooio::video_encoder::get_video_frame(Videooio::OutputStream*) (video_encoder.cpp:486)
==31277== by 0x269032: write_video_frame (video_encoder.cpp:499)
==31277== by 0x269032: Videooio::video_encoder::encode_one_frame() (video_encoder.cpp:553)
==31277== by 0x22BD89: Videooio::Application::main_loop() (Application.cpp:212)
==31277== by 0x21B007: Videooio::Application::Run() (Application.cpp:70)
==31277== by 0x219C94: main (main.cpp:22)
==31277== Address 0x50df9c8 is 744 bytes inside a block of size 752 alloc'd
==31277== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==31277== by 0x21A970: Videooio::Application::Run() (Application.cpp:40)
==31277== by 0x219C94: main (main.cpp:22)
I've diagnosed the problem down to the following lines but I'm not quite sure how to fix it:
Application.cpp
void Run()
{
...
40 encoder = new video_encoder(width, height, fps, duration);
...
while (second < duration)
{
auto* fbo = opengl_engine.glBuffer;
encoder->set_encode_framebuffer(fbo);
212 encoder->encode_one_Frame();
}
}
video_encoder.h:
namespace Videooio{
class video_encoder{
public:
video_encoder(int w, int h, unsigned int fps, unsigned int duration);
void set_encode_framebuffer(uint8_t* data, bool audio_only = false);
void encode_one_frame();
~video_encoder();
private:
int write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c,
AVStream *st, AVFrame *frame, AVPacket *pkt);
AVFrame *get_video_frame(OutputStream *ost);
int write_video_frame(AVFormatContext *oc, OutputStream *ost);
uint8_t *rgb_data;
int width;
int height;
void set_frame_yuv_from_rgb(AVFrame *frame, struct SwsContext *sws_context);
};
}
Here is opengl_engine, where fbo is allocated:
...
if (posix_memalign((void**)&glBuffer, 128, (gl_width * gl_height * 4) ) != 0)
{
ERROR("Couldn't allocate frame buffer ");
return false;
}
...
Here is where I set the rgb_data that is inside the encoder (Probably the culprit too) is set to the allocated fbo:
void video_encoder::set_audio_frame(AVFrame* audio, AVSampleFormat* format)
{
audio_data = *audio;
input_sample_fmt = *format;
}
rgb_data is set uninitialized up until this point before it's usage (I've tried mallocing it inside the constructor, which was a horrible practice, but doing so changed nothing.).
And here is where it's used and where valgrind mentions:
void video_encoder::set_frame_yuv_from_rgb(AVFrame *frame, struct SwsContext
*sws_context) {
const int in_linesize[1] = { 4 * width };
//uint8_t* dest[4] = { rgb_data, NULL, NULL, NULL };
sws_context = sws_getContext(
width, height, AV_PIX_FMT_RGBA,
width, height, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, 0, 0, 0);
440 std::cout << "Address: " << rgb_data << std::endl;
441 sws_scale(sws_context, (const uint8_t * const *)&rgb_data, in_linesize, 0,
442 height, frame->data, frame->linesize);
}
I'm not %100 sure whether rgb_data is causing this error or not but digging into sws_scale and finding where memcpy is used shows that rgb_data is used inside it.
I've tried changing the buffer size of glBuffer to no avail since valgrind allways says 744 bytes inside a block of size 752 the size of which the error mentions is not changing when I change glBuffers size, this led me to believe that rgb_data might not be the culprit. But it's still my best bet.
I've looked into these questions but I just can't seem to apply them to my own circumstance.
I'm using ubuntu.