-
Notifications
You must be signed in to change notification settings - Fork 36
fix: use real MJPG decoded size instead of negotiated resolution #520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1430,8 +1430,6 @@ int jpeg_init_decoder(int width, int height) | |
| } | ||
|
|
||
| codec_data->context->pix_fmt = AV_PIX_FMT_YUV422P; | ||
| codec_data->context->width = width; | ||
| codec_data->context->height = height; | ||
| //jpeg_ctx->context->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE); | ||
|
|
||
| // Initialize hardware device context (VA-API) | ||
|
|
@@ -1582,9 +1580,26 @@ int jpeg_decode(uint8_t *out_buf, uint8_t *in_buf, int size) | |
| printf(" - %s\n", getAvutil()->m_av_get_pix_fmt_name((enum AVPixelFormat)AV_PIX_FMT_YUV420P)); | ||
| } | ||
| #if LIBAVUTIL_VER_AT_LEAST(54,6) | ||
| getAvutil()->m_av_image_copy_to_buffer(jpeg_ctx->tmp_frame, jpeg_ctx->pic_size, | ||
| (const uint8_t * const*) sw_frame->data, sw_frame->linesize, | ||
| sw_frame->format, jpeg_ctx->width, jpeg_ctx->height, 1); | ||
| { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider extracting the duplicated buffer sizing and jpeg_ctx width/height update logic into a shared helper to simplify both decode paths and keep them in sync. You can reduce the new complexity by factoring the duplicated “ensure buffer and update size” logic into a small helper and reusing it in both call sites. For example, near the top of this file (or as static void jpeg_ensure_tmp_frame_capacity(enum AVPixelFormat fmt,
int dec_w, int dec_h)
{
int need = getAvutil()->m_av_image_get_buffer_size(fmt, dec_w, dec_h, 1);
if (need > 0 && (size_t)need > (size_t)jpeg_ctx->pic_size) {
uint8_t *p = realloc(jpeg_ctx->tmp_frame, (size_t)need);
if (p) {
jpeg_ctx->tmp_frame = p;
jpeg_ctx->pic_size = need;
}
/* if realloc fails, keep old buffer/size; behavior unchanged */
}
jpeg_ctx->width = dec_w;
jpeg_ctx->height = dec_h;
}Then both blocks shrink to the buffer copy plus the helper call, keeping behavior identical: NV12 path: {
int dec_w = sw_frame->width;
int dec_h = sw_frame->height;
jpeg_ensure_tmp_frame_capacity(sw_frame->format, dec_w, dec_h);
getAvutil()->m_av_image_copy_to_buffer(
jpeg_ctx->tmp_frame, jpeg_ctx->pic_size,
(const uint8_t * const*)sw_frame->data, sw_frame->linesize,
sw_frame->format, dec_w, dec_h, 1
);
}
if (sw_frame->format == AV_PIX_FMT_NV12) {
nv12_to_yu12(out_buf, jpeg_ctx->tmp_frame, jpeg_ctx->width, jpeg_ctx->height);
...
}Non-NV12 path: {
int dec_w = codec_data->picture->width;
int dec_h = codec_data->picture->height;
enum AVPixelFormat dec_fmt = codec_data->picture->format;
jpeg_ensure_tmp_frame_capacity(dec_fmt, dec_w, dec_h);
getAvutil()->m_av_image_copy_to_buffer(
jpeg_ctx->tmp_frame, jpeg_ctx->pic_size,
(const uint8_t * const*)codec_data->picture->data,
codec_data->picture->linesize,
dec_fmt, dec_w, dec_h, 1
);
}This keeps all the new dynamic sizing behavior (including |
||
| int dec_w = sw_frame->width; | ||
| int dec_h = sw_frame->height; | ||
|
sourcery-ai[bot] marked this conversation as resolved.
|
||
| int need = getAvutil()->m_av_image_get_buffer_size(sw_frame->format, dec_w, dec_h, 1); | ||
| if (need > 0 && (size_t)need > (size_t)jpeg_ctx->pic_size) { | ||
| uint8_t *p = realloc(jpeg_ctx->tmp_frame, (size_t)need); | ||
| if (!p) { | ||
| fprintf(stderr, "V4L2_CORE: (jpeg decoder) realloc failed for tmp_frame\n"); | ||
| getAvutil()->m_av_frame_free(&sw_frame); | ||
| return -1; | ||
| } | ||
| jpeg_ctx->tmp_frame = p; | ||
| jpeg_ctx->pic_size = need; | ||
| } | ||
| jpeg_ctx->width = dec_w; | ||
| jpeg_ctx->height = dec_h; | ||
| getAvutil()->m_av_image_copy_to_buffer(jpeg_ctx->tmp_frame, jpeg_ctx->pic_size, | ||
| (const uint8_t * const*) sw_frame->data, sw_frame->linesize, | ||
| sw_frame->format, dec_w, dec_h, 1); | ||
| } | ||
| if (sw_frame->format == AV_PIX_FMT_NV12) { | ||
| nv12_to_yu12(out_buf, jpeg_ctx->tmp_frame, jpeg_ctx->width, jpeg_ctx->height); | ||
| getAvutil()->m_av_frame_free(&sw_frame); | ||
|
|
@@ -1609,9 +1624,26 @@ int jpeg_decode(uint8_t *out_buf, uint8_t *in_buf, int size) | |
| } | ||
| decodeCount++; | ||
| } | ||
| getAvutil()->m_av_image_copy_to_buffer(jpeg_ctx->tmp_frame, jpeg_ctx->pic_size, | ||
| (const uint8_t * const*) codec_data->picture->data, codec_data->picture->linesize, | ||
| codec_data->context->pix_fmt, jpeg_ctx->width, jpeg_ctx->height, 1); | ||
| { | ||
| int dec_w = codec_data->picture->width; | ||
| int dec_h = codec_data->picture->height; | ||
| enum AVPixelFormat dec_fmt = codec_data->picture->format; | ||
| int need = getAvutil()->m_av_image_get_buffer_size(dec_fmt, dec_w, dec_h, 1); | ||
| if (need > 0 && (size_t)need > (size_t)jpeg_ctx->pic_size) { | ||
| uint8_t *p = realloc(jpeg_ctx->tmp_frame, (size_t)need); | ||
| if (!p) { | ||
| fprintf(stderr, "V4L2_CORE: (jpeg decoder) realloc failed for tmp_frame\n"); | ||
| return -1; | ||
| } | ||
| jpeg_ctx->tmp_frame = p; | ||
| jpeg_ctx->pic_size = need; | ||
| } | ||
| jpeg_ctx->width = dec_w; | ||
| jpeg_ctx->height = dec_h; | ||
| getAvutil()->m_av_image_copy_to_buffer(jpeg_ctx->tmp_frame, jpeg_ctx->pic_size, | ||
| (const uint8_t * const*) codec_data->picture->data, codec_data->picture->linesize, | ||
| dec_fmt, dec_w, dec_h, 1); | ||
| } | ||
| #else | ||
| avpicture_layout((AVPicture *) codec_data->picture, codec_data->dec_ctx->pix_fmt, | ||
| jpeg_ctx->width, jpeg_ctx->height, jpeg_ctx->tmp_frame, jpeg_ctx->pic_size); | ||
|
|
@@ -1640,6 +1672,27 @@ int jpeg_decode(uint8_t *out_buf, uint8_t *in_buf, int size) | |
|
|
||
| } | ||
|
|
||
| /* | ||
| * get real (decoded) frame size | ||
| * args: | ||
| * out_w - pointer to receive real decoded width (may be NULL) | ||
| * out_h - pointer to receive real decoded height (may be NULL) | ||
| * | ||
| * asserts: | ||
| * none | ||
| * | ||
| * returns: 0 on success (valid size available); negative if not initialized | ||
| * or not decoded yet | ||
| */ | ||
| int jpeg_get_decoded_size(int *out_w, int *out_h) | ||
| { | ||
| if (jpeg_ctx == NULL || jpeg_ctx->width <= 0 || jpeg_ctx->height <= 0) | ||
| return -1; | ||
| if (out_w) *out_w = jpeg_ctx->width; | ||
| if (out_h) *out_h = jpeg_ctx->height; | ||
| return 0; | ||
| } | ||
|
|
||
| /* | ||
| * close (m)jpeg decoder context | ||
| * args: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Guard against size_t overflow when computing
needand clarify trimming behavior.The expression
(size_t)real_w * (size_t)real_h * 3 / 2can overflowsize_tif a malformed stream reports very large dimensions, yielding a too-smallneedpassed torealloc. Please add a bound check (e.g., max width/height or verifying the product stays below a safe limit) and treat out-of-range sizes as an error. Also consider only shrinking whenneed < yuv_frame_max_sizeand growing whenneed > yuv_frame_max_sizeto avoid unnecessary reallocs if other code adjustsyuv_frame_max_sizefor other formats.Suggested implementation:
SIZE_MAXis available by including<limits.h>at the top oflibcam/libcam_v4l2core/frame_decoder.cif it is not already included.return -1;error paths assume this code is inside a function that returns anint-like status code; if this function has a different return type or usesgoto-based error handling, replace thereturn -1;with the appropriate error handling (e.g.,goto error;).yuv_frame_max_sizeset for other formats), you can remove theelse if (need < frame->yuv_frame_max_size)block, leaving only theneed > frame->yuv_frame_max_sizegrow case.