summaryrefslogtreecommitdiffstats
path: root/libhb/hb.c
diff options
context:
space:
mode:
authorBradley Sepos <[email protected]>2020-03-29 21:36:22 -0400
committerBradley Sepos <[email protected]>2020-06-15 17:18:46 -0400
commit0bceb3cdba3d22854ab85b5ea9b35aeae61b22cd (patch)
treeb3246591ff472b4e45f2981762dc890af1975bad /libhb/hb.c
parent5f53243424b4f9bead50079982556caaad31476e (diff)
libhb: Save/load preview images to/from disk using libjpeg-turbo.
Diffstat (limited to 'libhb/hb.c')
-rw-r--r--libhb/hb.c236
1 files changed, 186 insertions, 50 deletions
diff --git a/libhb/hb.c b/libhb/hb.c
index 2da229f98..183ab322d 100644
--- a/libhb/hb.c
+++ b/libhb/hb.c
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
+#include <turbojpeg.h>
#if HB_PROJECT_FEATURE_QSV
#include "handbrake/qsv_common.h"
@@ -458,52 +459,117 @@ hb_title_set_t * hb_get_title_set( hb_handle_t * h )
return &h->title_set;
}
-int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf )
+int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf, int format )
{
FILE * file;
char * filename;
char reason[80];
+ int format_chars = 4;
+ char format_string[format_chars];
- filename = hb_get_temporary_filename("%d_%d_%d", hb_get_instance_id(h),
- title, preview );
+ switch (format)
+ {
+ case HB_PREVIEW_FORMAT_YUV:
+ strncpy(format_string, "yuv", format_chars);
+ break;
+ case HB_PREVIEW_FORMAT_JPG:
+ strncpy(format_string, "jpg", format_chars);
+ break;
+ default:
+ hb_error("hb_save_preview: Unsupported preview format %d", format);
+ return -1;
+ }
+
+ filename = hb_get_temporary_filename("%d_%d_%d.%s", hb_get_instance_id(h),
+ title, preview, format_string );
file = hb_fopen(filename, "wb");
if (file == NULL)
{
if (strerror_r(errno, reason, 79) != 0)
strcpy(reason, "unknown -- strerror_r() failed");
-
hb_error("hb_save_preview: Failed to open %s (reason: %s)",
filename, reason);
free(filename);
return -1;
}
- int pp, hh;
- for( pp = 0; pp <= buf->f.max_plane; pp++ )
+ if (format == HB_PREVIEW_FORMAT_YUV)
{
- uint8_t *data = buf->plane[pp].data;
- int stride = buf->plane[pp].stride;
- int w = buf->plane[pp].width;
- int h = buf->plane[pp].height;
-
- for( hh = 0; hh < h; hh++ )
+ int pp, hh;
+ for( pp = 0; pp <= buf->f.max_plane; pp++ )
{
- if (fwrite( data, w, 1, file ) < w)
+ uint8_t *data = buf->plane[pp].data;
+ int stride = buf->plane[pp].stride;
+ int w = buf->plane[pp].width;
+ int h = buf->plane[pp].height;
+
+ for( hh = 0; hh < h; hh++ )
{
- if (ferror(file))
+ if (fwrite( data, w, 1, file ) < w)
{
- if (strerror_r(errno, reason, 79) != 0)
- strcpy(reason, "unknown -- strerror_r() failed");
+ if (ferror(file))
+ {
+ if (strerror_r(errno, reason, 79) != 0)
+ strcpy(reason, "unknown -- strerror_r() failed");
+ hb_error( "hb_save_preview: Failed to write line %d to %s "
+ "(reason: %s). Preview will be incomplete.",
+ hh, filename, reason );
+ goto done;
+ }
+ }
+ data += stride;
+ }
+ }
+ }
+ else if (format == HB_PREVIEW_FORMAT_JPG)
+ {
+ tjhandle jpeg_compressor = tjInitCompress();
+ const int jpeg_quality = 90;
+ unsigned long jpeg_size = 0;
+ unsigned char * jpeg_data = NULL;
+ int planes_max = 3;
+ int planes_stride[planes_max];
+ unsigned char * planes_data[planes_max];
+ int pp, compressor_result;
+ for (pp = 0; pp < 3; pp++)
+ {
+ planes_stride[pp] = buf->plane[pp].stride;
+ planes_data[pp] = buf->plane[pp].data;
+ }
- hb_error( "hb_save_preview: Failed to write line %d to %s "
- "(reason: %s). Preview will be incomplete.",
- hh, filename, reason );
- goto done;
+ compressor_result = tjCompressFromYUVPlanes(jpeg_compressor,
+ planes_data,
+ buf->plane[0].width,
+ planes_stride,
+ buf->plane[0].height,
+ TJSAMP_420,
+ &jpeg_data,
+ &jpeg_size,
+ jpeg_quality,
+ TJFLAG_FASTDCT);
+ if (compressor_result == 0)
+ {
+ size_t ret = fwrite(jpeg_data, jpeg_size, 1, file);
+ if ((ret < jpeg_size) && (ferror(file)))
+ {
+ if (strerror_r(errno, reason, 79) != 0)
+ {
+ strcpy(reason, "unknown -- strerror_r() failed");
}
+ hb_error("hb_save_preview: Failed to write to %s "
+ "(reason: %s).",
+ filename, reason);
}
- data += stride;
}
+ else
+ {
+ hb_error("hb_save_preview: JPEG compression failed for "
+ "preview image %s", filename);
+ }
+
+ tjDestroy(jpeg_compressor);
+ tjFree(jpeg_data);
}
done:
@@ -513,14 +579,36 @@ done:
return 0;
}
-hb_buffer_t * hb_read_preview(hb_handle_t * h, hb_title_t *title, int preview)
+hb_buffer_t * hb_read_preview(hb_handle_t * h, hb_title_t *title, int preview, int format)
{
- FILE * file;
- char * filename;
+ FILE * file = NULL;
+ char * filename = NULL;
char reason[80];
+ int format_chars = 4;
+ char format_string[format_chars];
+
+ hb_buffer_t * buf;
+ buf = hb_frame_buffer_init(AV_PIX_FMT_YUV420P,
+ title->geometry.width, title->geometry.height);
+
+ if (!buf)
+ goto done;
- filename = hb_get_temporary_filename("%d_%d_%d", hb_get_instance_id(h),
- title->index, preview);
+ switch (format)
+ {
+ case HB_PREVIEW_FORMAT_YUV:
+ strncpy(format_string, "yuv", format_chars);
+ break;
+ case HB_PREVIEW_FORMAT_JPG:
+ strncpy(format_string, "jpg", format_chars);
+ break;
+ default:
+ hb_error("hb_read_preview: Unsupported preview format %d", format);
+ return buf;
+ }
+
+ filename = hb_get_temporary_filename("%d_%d_%d.%s", hb_get_instance_id(h),
+ title->index, preview, format_string);
file = hb_fopen(filename, "rb");
if (file == NULL)
@@ -534,38 +622,86 @@ hb_buffer_t * hb_read_preview(hb_handle_t * h, hb_title_t *title, int preview)
return NULL;
}
- hb_buffer_t * buf;
- buf = hb_frame_buffer_init(AV_PIX_FMT_YUV420P,
- title->geometry.width, title->geometry.height);
-
- if (!buf)
- goto done;
+ if (format == HB_PREVIEW_FORMAT_YUV)
+ {
+ int pp, hh;
+ for (pp = 0; pp < 3; pp++)
+ {
+ uint8_t *data = buf->plane[pp].data;
+ int stride = buf->plane[pp].stride;
+ int w = buf->plane[pp].width;
+ int h = buf->plane[pp].height;
- int pp, hh;
- for (pp = 0; pp < 3; pp++)
+ for (hh = 0; hh < h; hh++)
+ {
+ if (fread(data, w, 1, file) < w)
+ {
+ if (ferror(file))
+ {
+ if (strerror_r(errno, reason, 79) != 0)
+ strcpy(reason, "unknown -- strerror_r() failed");
+
+ hb_error("hb_read_preview: Failed to read line %d from %s "
+ "(reason: %s). Preview will be incomplete.",
+ hh, filename, reason );
+ goto done;
+ }
+ }
+ data += stride;
+ }
+ }
+ }
+ else if (format == HB_PREVIEW_FORMAT_JPG)
{
- uint8_t *data = buf->plane[pp].data;
- int stride = buf->plane[pp].stride;
- int w = buf->plane[pp].width;
- int h = buf->plane[pp].height;
+ fseek(file, 0, SEEK_END);
+ unsigned long jpeg_size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ unsigned char * jpeg_data = tjAlloc(jpeg_size + 1);
+ jpeg_data[jpeg_size] = 0;
- for (hh = 0; hh < h; hh++)
+ size_t ret = fread(jpeg_data, jpeg_size, 1, file);
{
- if (fread(data, w, 1, file) < w)
+ if ((ret < jpeg_size) && (ferror(file)))
{
- if (ferror(file))
+ if (strerror_r(errno, reason, 79) != 0)
{
- if (strerror_r(errno, reason, 79) != 0)
- strcpy(reason, "unknown -- strerror_r() failed");
-
- hb_error("hb_read_preview: Failed to read line %d from %s "
- "(reason: %s). Preview will be incomplete.",
- hh, filename, reason );
- goto done;
+ strcpy(reason, "unknown -- strerror_r() failed");
}
+ hb_error("hb_read_preview: Failed to read from %s "
+ "(reason: %s).",
+ filename, reason);
+ tjFree(jpeg_data);
+ goto done;
}
- data += stride;
}
+
+ tjhandle jpeg_decompressor = tjInitDecompress();
+ int planes_max = 3;
+ int planes_stride[planes_max];
+ unsigned char * planes_data[planes_max];
+ int pp, decompressor_result;
+ for (pp = 0; pp < 3; pp++)
+ {
+ planes_stride[pp] = buf->plane[pp].stride;
+ planes_data[pp] = buf->plane[pp].data;
+ }
+
+ decompressor_result = tjDecompressToYUVPlanes(jpeg_decompressor,
+ jpeg_data,
+ jpeg_size,
+ planes_data,
+ buf->plane[0].width,
+ planes_stride,
+ buf->plane[0].height,
+ TJFLAG_FASTDCT);
+ if (decompressor_result != 0)
+ {
+ hb_error("hb_read_preview: JPEG decompression failed for "
+ "preview image %s", filename);
+ }
+
+ tjDestroy(jpeg_decompressor);
+ tjFree(jpeg_data);
}
done:
@@ -616,7 +752,7 @@ hb_image_t* hb_get_preview2(hb_handle_t * h, int title_idx, int picture,
goto fail;
}
- in_buf = hb_read_preview( h, title, picture );
+ in_buf = hb_read_preview( h, title, picture, HB_PREVIEW_FORMAT_JPG );
if ( in_buf == NULL )
{
goto fail;