MCPcopy Create free account
hub / github.com/PlotJuggler/PlotJuggler / encodeThumbnailJpeg

Function encodeThumbnailJpeg

pj_scene2D/core/src/thumbnail_codec.cpp:23–101  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

21} // namespace
22
23JpegThumbnail encodeThumbnailJpeg(const DecodedFrame& src_in, int max_width, int quality) {
24 JpegThumbnail out;
25 // Hardware decode emits NV12; the JPEG path below works in planar YUV420P, so
26 // deinterleave first. Cheap: only the ~1/N sampled frames reach the thumbnail cache.
27 DecodedFrame nv12_planar;
28 const DecodedFrame* src_ptr = &src_in;
29 if (src_in.format == PixelFormat::kNV12) {
30 nv12_planar = nv12ToYuv420p(src_in);
31 src_ptr = &nv12_planar;
32 }
33 const DecodedFrame& src = *src_ptr;
34 if (src.format != PixelFormat::kYUV420P || src.isNull() || src.width <= 0 || src.height <= 0) {
35 return out;
36 }
37 if (max_width <= 0) {
38 max_width = kThumbnailMaxWidth;
39 }
40
41 // Target dimensions: cap width, preserve aspect, keep even (YUV420 chroma).
42 int dst_w = src.width;
43 int dst_h = src.height;
44 if (dst_w > max_width) {
45 dst_h = evenDown(static_cast<int>(static_cast<int64_t>(dst_h) * max_width / dst_w));
46 dst_w = evenDown(max_width);
47 if (dst_h <= 0) {
48 dst_h = 2;
49 }
50 }
51
52 // YUV420P bytes to compress: the source verbatim (no downscale) or an sws copy.
53 const uint8_t* yuv = nullptr;
54 std::vector<uint8_t> scaled;
55 if (dst_w == src.width && dst_h == src.height) {
56 yuv = src.pixels->data();
57 } else {
58 scaled.resize(expectedBufferSize(dst_w, dst_h, PixelFormat::kYUV420P));
59 const int src_uvw = (src.width + 1) / 2;
60 const int src_uvh = (src.height + 1) / 2;
61 const int dst_uvw = (dst_w + 1) / 2;
62 const size_t src_y = static_cast<size_t>(src.width) * static_cast<size_t>(src.height);
63 const size_t src_uv = static_cast<size_t>(src_uvw) * static_cast<size_t>(src_uvh);
64 const size_t dst_y = static_cast<size_t>(dst_w) * static_cast<size_t>(dst_h);
65 const size_t dst_uv = static_cast<size_t>(dst_uvw) * static_cast<size_t>((dst_h + 1) / 2);
66 const uint8_t* sbase = src.pixels->data();
67 const uint8_t* src_planes[3] = {sbase, sbase + src_y, sbase + src_y + src_uv};
68 const int src_strides[3] = {src.width, src_uvw, src_uvw};
69 uint8_t* dst_planes[3] = {scaled.data(), scaled.data() + dst_y, scaled.data() + dst_y + dst_uv};
70 const int dst_strides[3] = {dst_w, dst_uvw, dst_uvw};
71
72 SwsContext* sws = sws_getContext(
73 src.width, src.height, AV_PIX_FMT_YUV420P, dst_w, dst_h, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, nullptr,
74 nullptr, nullptr);
75 if (sws == nullptr) {
76 return out;
77 }
78 sws_scale(sws, src_planes, src_strides, 0, src.height, dst_planes, dst_strides);
79 sws_freeContext(sws);
80 yuv = scaled.data();

Callers 2

buildThreadMethod · 0.85
TESTFunction · 0.85

Calls 6

nv12ToYuv420pFunction · 0.85
evenDownFunction · 0.85
expectedBufferSizeFunction · 0.85
isNullMethod · 0.45
dataMethod · 0.45
resizeMethod · 0.45

Tested by 1

TESTFunction · 0.68