1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2022, Ideas on Board Oy
*
* sdl_texture_mjpg.cpp - SDL Texture MJPG
*/
#include "sdl_texture_mjpg.h"
#include <iostream>
#include <setjmp.h>
#include <stdio.h>
#include <jpeglib.h>
using namespace libcamera;
struct JpegErrorManager : public jpeg_error_mgr {
JpegErrorManager()
{
jpeg_std_error(this);
error_exit = errorExit;
output_message = outputMessage;
}
static void errorExit(j_common_ptr cinfo)
{
JpegErrorManager *self =
static_cast<JpegErrorManager *>(cinfo->err);
longjmp(self->escape_, 1);
}
static void outputMessage([[maybe_unused]] j_common_ptr cinfo)
{
}
jmp_buf escape_;
};
SDLTextureMJPG::SDLTextureMJPG(const SDL_Rect &rect)
: SDLTexture(rect, SDL_PIXELFORMAT_RGB24, rect.w * 3),
rgb_(std::make_unique<unsigned char[]>(stride_ * rect.h))
{
}
int SDLTextureMJPG::decompress(Span<const uint8_t> data)
{
struct jpeg_decompress_struct cinfo;
JpegErrorManager errorManager;
if (setjmp(errorManager.escape_)) {
/* libjpeg found an error */
jpeg_destroy_decompress(&cinfo);
std::cerr << "JPEG decompression error" << std::endl;
return -EINVAL;
}
cinfo.err = &errorManager;
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo, data.data(), data.size());
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
for (int i = 0; cinfo.output_scanline < cinfo.output_height; ++i) {
JSAMPROW rowptr = rgb_.get() + i * stride_;
jpeg_read_scanlines(&cinfo, &rowptr, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return 0;
}
void SDLTextureMJPG::update(const std::vector<libcamera::Span<const uint8_t>> &data)
{
decompress(data[0]);
SDL_UpdateTexture(ptr_, nullptr, rgb_.get(), stride_);
}
|