diff options
author | Bradley Sepos <[email protected]> | 2020-03-29 21:36:22 -0400 |
---|---|---|
committer | Bradley Sepos <[email protected]> | 2020-06-15 17:18:46 -0400 |
commit | 0bceb3cdba3d22854ab85b5ea9b35aeae61b22cd (patch) | |
tree | b3246591ff472b4e45f2981762dc890af1975bad /libhb/hb.c | |
parent | 5f53243424b4f9bead50079982556caaad31476e (diff) |
libhb: Save/load preview images to/from disk using libjpeg-turbo.
Diffstat (limited to 'libhb/hb.c')
-rw-r--r-- | libhb/hb.c | 236 |
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; |