Skip to content

Commit 216eadc

Browse files
any1LMattsson
authored andcommitted
H264Libav: Use AVFrame for pixel format conversion buffer
This ensures that the buffer is allocated with the correct alignment and padding for use with sws_scale. This fixes out-of-bounds writes which would in some cases cause segmentation faults and/or heap corruption. (cherry picked from commit fff17ca)
1 parent 4c573f8 commit 216eadc

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

common/rfb/H264LibavDecoderContext.cxx

+17-10
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ bool H264LibavDecoderContext::initCodec() {
4343
os::AutoMutex lock(&mutex);
4444

4545
sws = NULL;
46-
swsBuffer = NULL;
4746
h264WorkBuffer = NULL;
4847
h264WorkBufferLength = 0;
4948

@@ -87,9 +86,6 @@ bool H264LibavDecoderContext::initCodec() {
8786
return false;
8887
}
8988

90-
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, rect.width(), rect.height(), 1);
91-
swsBuffer = new uint8_t[numBytes];
92-
9389
initialized = true;
9490
return true;
9591
}
@@ -101,8 +97,8 @@ void H264LibavDecoderContext::freeCodec() {
10197
return;
10298
av_parser_close(parser);
10399
avcodec_free_context(&avctx);
100+
av_frame_free(&rgbFrame);
104101
av_frame_free(&frame);
105-
delete[] swsBuffer;
106102
free(h264WorkBuffer);
107103
initialized = false;
108104
}
@@ -220,11 +216,22 @@ void H264LibavDecoderContext::decode(const uint8_t* h264_in_buffer,
220216
frame->width, frame->height, AV_PIX_FMT_RGB32,
221217
0, NULL, NULL, NULL);
222218

223-
int stride;
224-
pb->getBuffer(rect, &stride);
225-
int dst_linesize = stride * pb->getPF().bpp/8; // stride is in pixels, linesize is in bytes (stride x4). We need bytes
219+
if (rgbFrame && (rgbFrame->width != frame->width || rgbFrame->height != frame->height)) {
220+
av_frame_free(&rgbFrame);
221+
222+
}
223+
224+
if (!rgbFrame) {
225+
rgbFrame = av_frame_alloc();
226+
// TODO: Can we really assume that the pixel format will always be RGB32?
227+
rgbFrame->format = AV_PIX_FMT_RGB32;
228+
rgbFrame->width = frame->width;
229+
rgbFrame->height = frame->height;
230+
av_frame_get_buffer(rgbFrame, 0);
231+
}
226232

227-
sws_scale(sws, frame->data, frame->linesize, 0, frame->height, &swsBuffer, &dst_linesize);
233+
sws_scale(sws, frame->data, frame->linesize, 0, frame->height, rgbFrame->data,
234+
rgbFrame->linesize);
228235

229-
pb->imageRect(rect, swsBuffer, stride);
236+
pb->imageRect(rect, rgbFrame->data[0], rgbFrame->linesize[0] / 4);
230237
}

common/rfb/H264LibavDecoderContext.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ namespace rfb {
4747
AVCodecContext *avctx;
4848
AVCodecParserContext *parser;
4949
AVFrame* frame;
50+
AVFrame* rgbFrame = NULL;
5051
SwsContext* sws;
51-
uint8_t* swsBuffer;
5252
uint8_t* h264WorkBuffer;
5353
uint32_t h264WorkBufferLength;
5454
};

0 commit comments

Comments
 (0)