Skip to content

Commit 9fc8283

Browse files
committed
added enc opt to output the JPEG in a pinned buf
refers to GH-97
1 parent c80e3ce commit 9fc8283

File tree

6 files changed

+81
-14
lines changed

6 files changed

+81
-14
lines changed

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2025-05-23 - 0.27.4
2+
----------
3+
4+
- added encoder option to provide the encoded JPEG in a pinned buffer
5+
16
2025-05-19 - 0.27.3
27
----------
38

libgpujpeg/gpujpeg_encoder.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file
3-
* Copyright (c) 2011-2023, CESNET z.s.p.o
3+
* Copyright (c) 2011-2025, CESNET z.s.p.o
44
* Copyright (c) 2011, Silicon Genome, LLC.
55
*
66
* All rights reserved.
@@ -214,6 +214,16 @@ GPUJPEG_API int
214214
gpujpeg_encoder_suggest_restart_interval(const struct gpujpeg_image_parameters* param_image,
215215
gpujpeg_sampling_factor_t subsampling, bool interleaved, int verbose);
216216

217+
/// buffer returned from gpujpeg_encoder_encode() should be in pinned memory
218+
#define GPUJPEG_ENCODER_OPT_OUT_PINNED "enc_out_pinned"
219+
/**
220+
* sets encoder option
221+
* @retval GPUJPEG_NOERR option was sucessfully set
222+
* @retval GPUJPEG_ERROR invalid argument passed
223+
*/
224+
GPUJPEG_API int
225+
gpujpeg_encoder_set_option(struct gpujpeg_encoder* encoder, const char* opt, const char* val);
226+
217227
/**
218228
* Destory JPEG encoder
219229
*

src/gpujpeg_encoder.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,24 @@ gpujpeg_encoder_set_jpeg_header(struct gpujpeg_encoder *encoder, enum gpujpeg_he
646646
encoder->header_type = header_type;
647647
}
648648

649+
GPUJPEG_API int
650+
gpujpeg_encoder_set_option(struct gpujpeg_encoder* encoder, const char *opt, const char* val)
651+
{
652+
if ( encoder == NULL || opt == NULL || val == NULL ) {
653+
return GPUJPEG_ERROR;
654+
}
655+
if ( strcmp(opt, GPUJPEG_ENCODER_OPT_OUT_PINNED) == 0 ) {
656+
if ( val[0] != '0' && val[0] != '1' ) {
657+
ERROR_MSG("Unexpeceted value %s for " GPUJPEG_ENCODER_OPT_OUT_PINNED "\n", val);
658+
return GPUJPEG_ERROR;
659+
}
660+
encoder->writer->buffer_pinned = val[0] == '1';
661+
return GPUJPEG_NOERR;
662+
}
663+
ERROR_MSG("Invalid encoder option: %s!\n", opt);
664+
return GPUJPEG_ERROR;
665+
}
666+
649667
/* Documented at declaration */
650668
int
651669
gpujpeg_encoder_destroy(struct gpujpeg_encoder* encoder)

src/gpujpeg_writer.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file
3-
* Copyright (c) 2011-2023, CESNET z.s.p.o
3+
* Copyright (c) 2011-2025, CESNET z.s.p.o
44
* Copyright (c) 2011, Silicon Genome, LLC.
55
*
66
* All rights reserved.
@@ -53,6 +53,19 @@ gpujpeg_writer_create(void)
5353
return writer;
5454
}
5555

56+
static void free_buffer(struct gpujpeg_writer *writer) {
57+
if ( writer->buffer == NULL ) {
58+
return;
59+
}
60+
if ( writer->buffer_pinned ) {
61+
cudaFreeHost(writer->buffer);
62+
}
63+
else {
64+
free(writer->buffer);
65+
}
66+
writer->buffer = NULL;
67+
}
68+
5669
/* Documented at declaration */
5770
int
5871
gpujpeg_writer_init(struct gpujpeg_writer* writer, int comp_count, struct gpujpeg_image_parameters* param_image)
@@ -63,10 +76,13 @@ gpujpeg_writer_init(struct gpujpeg_writer* writer, int comp_count, struct gpujpe
6376

6477
if (buffer_size > writer->buffer_allocated_size) {
6578
writer->buffer_allocated_size = 0;
66-
if (writer->buffer != NULL) {
67-
free(writer->buffer);
79+
free_buffer(writer);
80+
if ( writer->buffer_pinned ) {
81+
cudaMallocHost((void**)&writer->buffer, buffer_size * sizeof(uint8_t));
82+
}
83+
else {
84+
writer->buffer = (uint8_t*)malloc(buffer_size * sizeof(uint8_t));
6885
}
69-
writer->buffer = (uint8_t *) malloc(buffer_size * sizeof(uint8_t));
7086
if (writer->buffer == NULL) {
7187
return -1;
7288
}
@@ -84,9 +100,7 @@ int
84100
gpujpeg_writer_destroy(struct gpujpeg_writer* writer)
85101
{
86102
assert(writer != NULL);
87-
if (writer->buffer != NULL) {
88-
free(writer->buffer);
89-
}
103+
free_buffer(writer);
90104
free(writer);
91105
return 0;
92106
}

src/gpujpeg_writer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file
3-
* Copyright (c) 2011-2023, CESNET z.s.p.o
3+
* Copyright (c) 2011-2025, CESNET z.s.p.o
44
* Copyright (c) 2011, Silicon Genome, LLC.
55
*
66
* All rights reserved.
@@ -31,6 +31,7 @@
3131
#ifndef GPUJPEG_WRITER_H
3232
#define GPUJPEG_WRITER_H
3333

34+
#include <stdbool.h>
3435
#include <stddef.h>
3536
#include "../libgpujpeg/gpujpeg_type.h"
3637

@@ -51,6 +52,7 @@ struct gpujpeg_writer
5152
uint8_t* buffer_current;
5253
// Allocate size of output buffer.
5354
size_t buffer_allocated_size;
55+
bool buffer_pinned; ///< buffer should be allocated in pinned memory
5456

5557
// Segment info buffers (every buffer is placed inside another header)
5658
uint8_t* segment_info[GPUJPEG_MAX_SEGMENT_INFO_HEADER_COUNT];

src/main.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,21 @@ struct coder_opts
283283
char* val;
284284
};
285285
static bool
286-
assign_decoder_opt(struct coder_opts* opts, char *optarg)
286+
assign_coder_opt(struct coder_opts* encoder_opts, struct coder_opts* decoder_opts, char* optarg)
287287
{
288-
char *opt = optarg;
289-
char *delim = strchr(optarg, '=');
288+
char* opt = optarg;
289+
char* delim = strchr(optarg, '=');
290290
if ( delim == NULL ) {
291291
fprintf(stderr, "No value for %s!\n", optarg);
292292
return false;
293293
}
294+
if ( strncmp(optarg, "enc_", 4) != 0 && strncmp(optarg, "dec_", 4) != 0 ) {
295+
fprintf(stderr, "Option should start with either enc_ or dec_, given %s!\n", optarg);
296+
return false;
297+
}
294298
*delim = '\0';
295299
char *val = delim + 1;
300+
struct coder_opts* opts = strncmp(optarg, "enc_", 4) == 0 ? encoder_opts : decoder_opts;
296301
for ( int i = 0; i < CODER_OPTS_COUNT; ++i ) {
297302
if ( opts[i].opt == NULL ) {
298303
opts[i].opt = opt;
@@ -304,6 +309,18 @@ assign_decoder_opt(struct coder_opts* opts, char *optarg)
304309
return false;
305310
}
306311
static bool
312+
set_encoder_opts(struct gpujpeg_encoder* encoder, const struct coder_opts* opts)
313+
{
314+
while ( (*opts).opt != NULL ) {
315+
if ( gpujpeg_encoder_set_option(encoder, (*opts).opt, (*opts).val) != 0 ) {
316+
return false;
317+
}
318+
opts++;
319+
}
320+
321+
return true;
322+
}
323+
static bool
307324
set_decoder_opts(struct gpujpeg_decoder* decoder, const struct coder_opts* opts)
308325
{
309326
while ( (*opts).opt != NULL ) {
@@ -350,6 +367,7 @@ main(int argc, char *argv[])
350367
_Bool use_opengl = 0;
351368
bool debug = false;
352369
struct coder_opts decoder_options[CODER_OPTS_COUNT + 1] = {0};
370+
struct coder_opts encoder_options[CODER_OPTS_COUNT + 1] = {0};
353371

354372
// Flags
355373
struct options opts = {.subsampling = GPUJPEG_SUBSAMPLING_UNKNOWN,
@@ -508,7 +526,7 @@ main(int argc, char *argv[])
508526
debug = true;
509527
break;
510528
case 'O':
511-
if ( !assign_decoder_opt(decoder_options, optarg) ) {
529+
if ( !assign_coder_opt(encoder_options, decoder_options, optarg) ) {
512530
return 1;
513531
}
514532
break;
@@ -608,7 +626,7 @@ main(int argc, char *argv[])
608626

609627
// Create encoder
610628
struct gpujpeg_encoder* encoder = gpujpeg_encoder_create(NULL);
611-
if ( encoder == NULL ) {
629+
if ( encoder == NULL || !set_encoder_opts(encoder, encoder_options) ) {
612630
fprintf(stderr, "Failed to create encoder!\n");
613631
return -1;
614632
}

0 commit comments

Comments
 (0)