diff options
author | jstebbins <[email protected]> | 2014-07-29 18:40:38 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2014-07-29 18:40:38 +0000 |
commit | 6942656aeac26e63e87d8c1772ccec3e64b437e1 (patch) | |
tree | e82d337589c6bcfafe17963337f99ad6d41ec890 | |
parent | 56680a9b967772ca6eb9112ac6f2a9e9bbe7244b (diff) |
libhb: add new function for retrieving previews
This new function has a couple advantages over the old one (which we
should phase out).
It does not require hb_job_t as a parameter, instead it uses hb_ui_geometry_t
which is a smaller and simpler struct. The entire job struct is overkill as
input to this function.
It returns an hb_image_t that fully describes the returned image instead of
just a uint8_t array. The caller does not have to make assumptions about image
size, line stide, or pixel format since hb_image_t specifies these things.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6242 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | gtk/src/hb-backend.c | 29 | ||||
-rw-r--r-- | libhb/common.c | 16 | ||||
-rw-r--r-- | libhb/common.h | 21 | ||||
-rw-r--r-- | libhb/fifo.c | 52 | ||||
-rw-r--r-- | libhb/hb.c | 122 | ||||
-rw-r--r-- | libhb/hb.h | 12 | ||||
-rw-r--r-- | libhb/internal.h | 3 |
7 files changed, 200 insertions, 55 deletions
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index dc6359445..175d523cc 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -5046,18 +5046,8 @@ ghb_get_preview_image( uiGeo.par.num = 1; uiGeo.par.den = 1; - // Populate job with things needed by hb_get_preview - hb_job_t *job = hb_job_init((hb_title_t*)title); - job->width = uiGeo.width; - job->height = uiGeo.height; - job->deinterlace = deinterlace; - memcpy(job->crop, uiGeo.crop, sizeof(int[4])); - - // Make sure we have a big enough buffer to receive the image from libhb - guint8 *buffer = g_malloc(uiGeo.width * uiGeo.height * 4); - - hb_get_preview( h_scan, job, index, buffer ); - hb_job_close( &job ); + hb_image_t *image; + image = hb_get_preview2(h_scan, title->index, index, &uiGeo, deinterlace); // Create an GdkPixbuf and copy the libhb image into it, converting it from // libhb's format something suitable. @@ -5065,10 +5055,10 @@ ghb_get_preview_image( // BGRA format. Alpha is ignored. GdkPixbuf *preview; preview = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, - uiGeo.width, uiGeo.height); + image->width, image->height); guint8 *pixels = gdk_pixbuf_get_pixels(preview); - guint8 *src_line = buffer; + guint8 *src_line = image->data; guint8 *dst = pixels; gint ii, jj; @@ -5076,11 +5066,11 @@ ghb_get_preview_image( gint stride = gdk_pixbuf_get_rowstride(preview); guint8 *tmp; - for (ii = 0; ii < uiGeo.height; ii++) + for (ii = 0; ii < image->height; ii++) { guint32 *src = (guint32*)src_line; tmp = dst; - for (jj = 0; jj < uiGeo.width; jj++) + for (jj = 0; jj < image->width; jj++) { tmp[0] = src[0] >> 16; tmp[1] = src[0] >> 8; @@ -5088,7 +5078,7 @@ ghb_get_preview_image( tmp += channels; src++; } - src_line += uiGeo.width * 4; + src_line += image->plane[0].stride; dst += stride; } gint w = ghb_settings_get_int(ud->settings, "scale_width"); @@ -5107,8 +5097,8 @@ ghb_get_preview_image( *out_width = w; *out_height = h; - int previewWidth = uiGeo.width; - int previewHeight = uiGeo.height; + int previewWidth = image->width; + int previewHeight = image->height; // If the preview is too large to fit the screen, reduce it's size. if (ghb_settings_get_boolean(ud->prefs, "reduce_hd_preview")) @@ -5167,6 +5157,7 @@ ghb_get_preview_image( // Right hash_pixbuf(preview, previewWidth-c3, c0, c3, h, 32, 1); } + hb_image_close(&image); return preview; } diff --git a/libhb/common.c b/libhb/common.c index 0bb2eafd5..7c4a97eca 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -3119,6 +3119,22 @@ static void job_clean( hb_job_t * job ) } } +hb_title_t * hb_find_title_by_index( hb_handle_t *h, int title_index ) +{ + hb_title_set_t *title_set = hb_get_title_set( h ); + int ii; + + for (ii = 0; ii < hb_list_count(title_set->list_title); ii++) + { + hb_title_t *title = hb_list_item(title_set->list_title, ii); + if (title_index == title->index) + { + return title; + } + } + return NULL; +} + /* * Create a pristine job structure from a title * title_index is 1 based diff --git a/libhb/common.h b/libhb/common.h index c3bbc2c21..2882bdf37 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -81,6 +81,7 @@ typedef struct hb_container_s hb_container_t; typedef struct hb_rational_s hb_rational_t; typedef struct hb_geometry_s hb_geometry_t; typedef struct hb_ui_geometry_s hb_ui_geometry_t; +typedef struct hb_image_s hb_image_t; typedef struct hb_job_s hb_job_t; typedef struct hb_title_set_s hb_title_set_t; typedef struct hb_title_s hb_title_t; @@ -263,6 +264,26 @@ struct hb_ui_geometry_s hb_rational_t dar; // Display aspect used in custom anamorphic }; +struct hb_image_s +{ + int format; + int width; + int height; + uint8_t *data; + + struct image_plane + { + uint8_t *data; + int width; + int height; + int stride; + int height_stride; + int size; + } plane[4]; +}; + +void hb_image_close(hb_image_t **_image); + // Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle_config_s.cs when changing this struct struct hb_subtitle_config_s { diff --git a/libhb/fifo.c b/libhb/fifo.c index 043790e17..0e05ea031 100644 --- a/libhb/fifo.c +++ b/libhb/fifo.c @@ -681,6 +681,58 @@ void hb_buffer_move_subs( hb_buffer_t * dst, hb_buffer_t * src ) } +hb_image_t * hb_buffer_to_image(hb_buffer_t *buf) +{ + hb_image_t *image = calloc(1, sizeof(hb_image_t)); + +#if defined( SYS_DARWIN ) || defined( SYS_FREEBSD ) || defined( SYS_MINGW ) + image->data = malloc( buf->size ); +#elif defined( SYS_CYGWIN ) + /* FIXME */ + image->data = malloc( buf->size + 17 ); +#else + image->data = memalign( 16, buf->size ); +#endif + if (image->data == NULL) + { + free(image); + return NULL; + } + + image->format = buf->f.fmt; + image->width = buf->f.width; + image->height = buf->f.height; + memcpy(image->data, buf->data, buf->size); + + int p; + uint8_t *data = image->data; + for (p = 0; p < 4; p++) + { + image->plane[p].data = data; + image->plane[p].width = buf->plane[p].width; + image->plane[p].height = buf->plane[p].height; + image->plane[p].stride = buf->plane[p].stride; + image->plane[p].height_stride = buf->plane[p].height_stride; + image->plane[p].size = buf->plane[p].size; + data += image->plane[p].size; + } + return image; +} + +void hb_image_close(hb_image_t **_image) +{ + if (_image == NULL) + return; + + hb_image_t * image = *_image; + if (image != NULL) + { + free(image->data); + free(image); + *_image = NULL; + } +} + hb_fifo_t * hb_fifo_init( int capacity, int thresh ) { hb_fifo_t * f; diff --git a/libhb/hb.c b/libhb/hb.c index e6036587f..e7c9c22bf 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -671,64 +671,124 @@ int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf ) return 0; } -hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ) +hb_buffer_t * hb_read_preview(hb_handle_t * h, hb_title_t *title, int preview) { FILE * file; char filename[1024]; - hb_title_set_t *title_set; - hb_title_t * title = NULL; - - title_set = hb_get_title_set(h); - - int ii; - for (ii = 0; ii < hb_list_count(title_set->list_title); ii++) - { - title = hb_list_item( title_set->list_title, ii); - if (title != NULL && title->index == title_idx) - { - break; - } - title = NULL; - } - if (title == NULL) - { - hb_error( "hb_read_preview: invalid title (%d)", title_idx ); - return NULL; - } - - hb_get_tempory_filename( h, filename, "%d_%d_%d", - hb_get_instance_id(h), title_idx, preview ); + hb_get_tempory_filename(h, filename, "%d_%d_%d", + hb_get_instance_id(h), title->index, preview); file = hb_fopen(filename, "rb"); - if( !file ) + if (!file) { hb_error( "hb_read_preview: fopen failed (%s)", filename ); return NULL; } hb_buffer_t * buf; - buf = hb_frame_buffer_init( AV_PIX_FMT_YUV420P, title->width, title->height ); + buf = hb_frame_buffer_init(AV_PIX_FMT_YUV420P, title->width, title->height); int pp, hh; - for( pp = 0; pp < 3; pp++ ) + 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; - for( hh = 0; hh < h; hh++ ) + for (hh = 0; hh < h; hh++) { - fread( data, w, 1, file ); + fread(data, w, 1, file); data += stride; } } - fclose( file ); + fclose(file); return buf; } +hb_image_t* hb_get_preview2(hb_handle_t * h, int title_idx, int picture, + hb_ui_geometry_t *ui_geo, int deinterlace) +{ + char filename[1024]; + hb_buffer_t * in_buf, * deint_buf = NULL, * preview_buf; + uint32_t swsflags; + AVPicture pic_in, pic_preview, pic_deint, pic_crop; + struct SwsContext * context; + + int width = ui_geo->width * ui_geo->par.num / ui_geo->par.den; + int height = ui_geo->height; + + swsflags = SWS_LANCZOS | SWS_ACCURATE_RND; + + preview_buf = hb_frame_buffer_init(AV_PIX_FMT_RGB32, width, height); + hb_avpicture_fill( &pic_preview, preview_buf ); + + // Allocate the AVPicture frames and fill in + + memset( filename, 0, 1024 ); + + hb_title_t * title; + title = hb_find_title_by_index(h, title_idx); + if (title == NULL) + { + hb_error( "hb_get_preview2: invalid title (%d)", title_idx ); + return NULL; + } + + in_buf = hb_read_preview( h, title, picture ); + if ( in_buf == NULL ) + { + return NULL; + } + + hb_avpicture_fill( &pic_in, in_buf ); + + if (deinterlace) + { + // Deinterlace and crop + deint_buf = hb_frame_buffer_init( AV_PIX_FMT_YUV420P, + title->width, title->height ); + hb_deinterlace(deint_buf, in_buf); + hb_avpicture_fill( &pic_deint, deint_buf ); + + av_picture_crop(&pic_crop, &pic_deint, AV_PIX_FMT_YUV420P, + ui_geo->crop[0], ui_geo->crop[2] ); + } + else + { + // Crop + av_picture_crop(&pic_crop, &pic_in, AV_PIX_FMT_YUV420P, + ui_geo->crop[0], ui_geo->crop[2] ); + } + + // Get scaling context + context = hb_sws_get_context( + title->width - (ui_geo->crop[2] + ui_geo->crop[3]), + title->height - (ui_geo->crop[0] + ui_geo->crop[1]), + AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGB32, + swsflags); + + // Scale + sws_scale(context, + (const uint8_t* const *)pic_crop.data, pic_crop.linesize, + 0, title->height - (ui_geo->crop[0] + ui_geo->crop[1]), + pic_preview.data, pic_preview.linesize); + + // Free context + sws_freeContext( context ); + + hb_image_t *image = hb_buffer_to_image(preview_buf); + + // Clean up + hb_buffer_close( &in_buf ); + hb_buffer_close( &deint_buf ); + hb_buffer_close( &preview_buf ); + + return image; +} + /** * Create preview image of desired title a index of picture. * @param h Handle to hb_handle_t. @@ -759,7 +819,7 @@ void hb_get_preview( hb_handle_t * h, hb_job_t * job, int picture, memset( filename, 0, 1024 ); - in_buf = hb_read_preview( h, title->index, picture ); + in_buf = hb_read_preview( h, title, picture ); if ( in_buf == NULL ) { return; diff --git a/libhb/hb.h b/libhb/hb.h index cad630650..2d32e1aef 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -68,9 +68,12 @@ int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int thre // JJJ: title->job? int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf ); -hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ); +hb_buffer_t * hb_read_preview( hb_handle_t * h, hb_title_t *title, + int preview ); void hb_get_preview( hb_handle_t *, hb_job_t *, int, uint8_t * ); +hb_image_t * hb_get_preview2(hb_handle_t * h, int title_idx, int picture, + hb_ui_geometry_t *ui_geo, int deinterlace); void hb_set_anamorphic_size2(hb_geometry_t *src_geo, hb_ui_geometry_t *ui_geo, hb_geometry_t *result); @@ -83,12 +86,13 @@ void hb_add_filter( hb_job_t * job, hb_filter_object_t * filter, /* Handling jobs */ int hb_count( hb_handle_t * ); -hb_job_t * hb_job( hb_handle_t *, int ); +hb_job_t * hb_job( hb_handle_t *, int ); void hb_add( hb_handle_t *, hb_job_t * ); void hb_rem( hb_handle_t *, hb_job_t * ); -hb_job_t * hb_job_init_by_index( hb_handle_t *h, int title_index ); -hb_job_t * hb_job_init( hb_title_t * title ); +hb_title_t * hb_find_title_by_index( hb_handle_t *h, int title_index ); +hb_job_t * hb_job_init_by_index( hb_handle_t *h, int title_index ); +hb_job_t * hb_job_init( hb_title_t * title ); void hb_job_reset( hb_job_t * job ); void hb_job_close( hb_job_t ** job ); diff --git a/libhb/internal.h b/libhb/internal.h index ed7eab367..c71b23ecd 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -106,7 +106,7 @@ struct hb_buffer_s int fmt; } f; - struct plane + struct buffer_plane { uint8_t * data; int stride; @@ -163,6 +163,7 @@ hb_buffer_t * hb_buffer_dup( const hb_buffer_t * src ); int hb_buffer_copy( hb_buffer_t * dst, const hb_buffer_t * src ); void hb_buffer_swap_copy( hb_buffer_t *src, hb_buffer_t *dst ); void hb_buffer_move_subs( hb_buffer_t * dst, hb_buffer_t * src ); +hb_image_t * hb_buffer_to_image(hb_buffer_t *buf); hb_fifo_t * hb_fifo_init( int capacity, int thresh ); int hb_fifo_size( hb_fifo_t * ); |