WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / hb.c
blobe8418e7413bc455fa259ae78d0633775e8e09d8c
1 /* hb.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "hb.h"
11 #include "opencl.h"
12 #include "hbffmpeg.h"
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <fcntl.h>
17 #ifdef USE_QSV
18 #include "qsv_common.h"
19 #endif
21 #if defined( SYS_MINGW )
22 #include <io.h>
23 #if defined( PTW32_STATIC_LIB )
24 #include <pthread.h>
25 #endif
26 #endif
28 struct hb_handle_s
30 int id;
32 /* The "Check for update" thread */
33 int build;
34 char version[32];
35 hb_thread_t * update_thread;
37 /* This thread's only purpose is to check other threads'
38 states */
39 volatile int die;
40 hb_thread_t * main_thread;
41 int pid;
43 /* DVD/file scan thread */
44 hb_title_set_t title_set;
45 hb_thread_t * scan_thread;
47 /* The thread which processes the jobs. Others threads are launched
48 from this one (see work.c) */
49 hb_list_t * jobs;
50 hb_job_t * current_job;
51 volatile int work_die;
52 hb_error_code work_error;
53 hb_thread_t * work_thread;
55 hb_lock_t * state_lock;
56 hb_state_t state;
58 int paused;
59 hb_lock_t * pause_lock;
60 /* For MacGui active queue
61 increments each time the scan thread completes*/
62 int scanCount;
63 volatile int scan_die;
65 /* Stash of persistent data between jobs, for stuff
66 like correcting frame count and framerate estimates
67 on multi-pass encodes where frames get dropped. */
68 hb_interjob_t * interjob;
70 // power management opaque pointer
71 void * system_sleep_opaque;
73 // When hardware decoding, scan must also use hardware so that
74 // libav hardware decode contest is used. So set hardware
75 // decoding as a global property on the hb instance.
76 hb_hwd_t hwd;
79 hb_work_object_t * hb_objects = NULL;
80 int hb_instance_counter = 0;
82 void hb_hwd_set_enable( hb_handle_t *h, uint8_t enable )
84 h->hwd.enable = enable;
87 int hb_hwd_enabled( hb_handle_t *h )
89 return h->hwd.enable;
92 hb_hwd_t * hb_hwd_get_context( hb_handle_t *h )
94 return &h->hwd;
97 static void thread_func( void * );
99 static int ff_lockmgr_cb(void **mutex, enum AVLockOp op)
101 switch ( op )
103 case AV_LOCK_CREATE:
105 *mutex = hb_lock_init();
106 } break;
107 case AV_LOCK_DESTROY:
109 hb_lock_close( (hb_lock_t**)mutex );
110 } break;
111 case AV_LOCK_OBTAIN:
113 hb_lock( (hb_lock_t*)*mutex );
114 } break;
115 case AV_LOCK_RELEASE:
117 hb_unlock( (hb_lock_t*)*mutex );
118 } break;
119 default:
120 break;
122 return 0;
125 void hb_avcodec_init()
127 av_lockmgr_register(ff_lockmgr_cb);
128 av_register_all();
129 #ifdef _WIN64
130 // avresample's assembly optimizations can cause crashes under Win x86_64
131 // (see http://bugzilla.libav.org/show_bug.cgi?id=496)
132 // disable AVX and FMA4 as a workaround
133 hb_deep_log(2, "hb_avcodec_init: Windows x86_64, disabling AVX and FMA4");
134 int cpu_flags = av_get_cpu_flags() & ~AV_CPU_FLAG_AVX & ~AV_CPU_FLAG_FMA4;
135 av_set_cpu_flags_mask(cpu_flags);
136 #endif
139 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec,
140 AVDictionary **av_opts, int thread_count)
142 int ret;
144 if ((thread_count == HB_FFMPEG_THREADS_AUTO || thread_count > 0) &&
145 (codec->type == AVMEDIA_TYPE_VIDEO))
147 avctx->thread_count = (thread_count == HB_FFMPEG_THREADS_AUTO) ?
148 hb_get_cpu_count() / 2 + 1 : thread_count;
149 avctx->thread_type = FF_THREAD_FRAME|FF_THREAD_SLICE;
150 avctx->thread_safe_callbacks = 1;
152 else
154 avctx->thread_count = 1;
157 if (codec->capabilities & CODEC_CAP_EXPERIMENTAL)
159 // "experimental" encoders will not open without this
160 avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
163 ret = avcodec_open2(avctx, codec, av_opts);
164 return ret;
167 int hb_avcodec_close(AVCodecContext *avctx)
169 int ret;
170 ret = avcodec_close(avctx);
171 return ret;
175 int hb_avpicture_fill(AVPicture *pic, hb_buffer_t *buf)
177 int ret, ii;
179 for (ii = 0; ii < 4; ii++)
180 pic->linesize[ii] = buf->plane[ii].stride;
182 ret = av_image_fill_pointers(pic->data, buf->f.fmt,
183 buf->plane[0].height_stride,
184 buf->data, pic->linesize);
185 if (ret != buf->size)
187 hb_error("Internal error hb_avpicture_fill expected %d, got %d",
188 buf->size, ret);
190 return ret;
193 static int handle_jpeg(enum AVPixelFormat *format)
195 switch (*format)
197 case AV_PIX_FMT_YUVJ420P: *format = AV_PIX_FMT_YUV420P; return 1;
198 case AV_PIX_FMT_YUVJ422P: *format = AV_PIX_FMT_YUV422P; return 1;
199 case AV_PIX_FMT_YUVJ444P: *format = AV_PIX_FMT_YUV444P; return 1;
200 case AV_PIX_FMT_YUVJ440P: *format = AV_PIX_FMT_YUV440P; return 1;
201 default: return 0;
205 struct SwsContext*
206 hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat,
207 int dstW, int dstH, enum AVPixelFormat dstFormat,
208 int flags)
210 struct SwsContext * ctx;
212 ctx = sws_alloc_context();
213 if ( ctx )
215 int srcRange, dstRange;
217 srcRange = handle_jpeg(&srcFormat);
218 dstRange = handle_jpeg(&dstFormat);
219 /* enable this when implemented in Libav
220 flags |= SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP;
223 av_opt_set_int(ctx, "srcw", srcW, 0);
224 av_opt_set_int(ctx, "srch", srcH, 0);
225 av_opt_set_int(ctx, "src_range", srcRange, 0);
226 av_opt_set_int(ctx, "src_format", srcFormat, 0);
227 av_opt_set_int(ctx, "dstw", dstW, 0);
228 av_opt_set_int(ctx, "dsth", dstH, 0);
229 av_opt_set_int(ctx, "dst_range", dstRange, 0);
230 av_opt_set_int(ctx, "dst_format", dstFormat, 0);
231 av_opt_set_int(ctx, "sws_flags", flags, 0);
233 sws_setColorspaceDetails( ctx,
234 sws_getCoefficients( SWS_CS_DEFAULT ), // src colorspace
235 srcRange, // src range 0 = MPG, 1 = JPG
236 sws_getCoefficients( SWS_CS_DEFAULT ), // dst colorspace
237 dstRange, // dst range 0 = MPG, 1 = JPG
238 0, // brightness
239 1 << 16, // contrast
240 1 << 16 ); // saturation
242 if (sws_init_context(ctx, NULL, NULL) < 0) {
243 hb_error("Cannot initialize resampling context");
244 sws_freeContext(ctx);
245 ctx = NULL;
248 return ctx;
251 uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode)
253 uint64_t ff_layout = 0;
254 int mode = AV_MATRIX_ENCODING_NONE;
255 switch (hb_mixdown)
257 // Passthru
258 case HB_AMIXDOWN_NONE:
259 break;
261 case HB_AMIXDOWN_MONO:
262 case HB_AMIXDOWN_LEFT:
263 case HB_AMIXDOWN_RIGHT:
264 ff_layout = AV_CH_LAYOUT_MONO;
265 break;
267 case HB_AMIXDOWN_DOLBY:
268 ff_layout = AV_CH_LAYOUT_STEREO;
269 mode = AV_MATRIX_ENCODING_DOLBY;
270 break;
272 case HB_AMIXDOWN_DOLBYPLII:
273 ff_layout = AV_CH_LAYOUT_STEREO;
274 mode = AV_MATRIX_ENCODING_DPLII;
275 break;
277 case HB_AMIXDOWN_STEREO:
278 ff_layout = AV_CH_LAYOUT_STEREO;
279 break;
281 case HB_AMIXDOWN_5POINT1:
282 ff_layout = AV_CH_LAYOUT_5POINT1;
283 break;
285 case HB_AMIXDOWN_6POINT1:
286 ff_layout = AV_CH_LAYOUT_6POINT1;
287 break;
289 case HB_AMIXDOWN_7POINT1:
290 ff_layout = AV_CH_LAYOUT_7POINT1;
291 break;
293 case HB_AMIXDOWN_5_2_LFE:
294 ff_layout = (AV_CH_LAYOUT_5POINT1_BACK|
295 AV_CH_FRONT_LEFT_OF_CENTER|
296 AV_CH_FRONT_RIGHT_OF_CENTER);
297 break;
299 default:
300 ff_layout = AV_CH_LAYOUT_STEREO;
301 hb_log("hb_ff_mixdown_xlat: unsupported mixdown %d", hb_mixdown);
302 break;
304 if (downmix_mode != NULL)
305 *downmix_mode = mode;
306 return ff_layout;
310 * Set sample format to the request format if supported by the codec.
311 * The planar/packed variant of the requested format is the next best thing.
313 void hb_ff_set_sample_fmt(AVCodecContext *context, AVCodec *codec,
314 enum AVSampleFormat request_sample_fmt)
316 if (context != NULL && codec != NULL &&
317 codec->type == AVMEDIA_TYPE_AUDIO && codec->sample_fmts != NULL)
319 const enum AVSampleFormat *fmt;
320 enum AVSampleFormat next_best_fmt;
322 next_best_fmt = (av_sample_fmt_is_planar(request_sample_fmt) ?
323 av_get_packed_sample_fmt(request_sample_fmt) :
324 av_get_planar_sample_fmt(request_sample_fmt));
326 context->request_sample_fmt = AV_SAMPLE_FMT_NONE;
328 for (fmt = codec->sample_fmts; *fmt != AV_SAMPLE_FMT_NONE; fmt++)
330 if (*fmt == request_sample_fmt)
332 context->request_sample_fmt = request_sample_fmt;
333 break;
335 else if (*fmt == next_best_fmt)
337 context->request_sample_fmt = next_best_fmt;
342 * When encoding and AVCodec.sample_fmts exists, avcodec_open2()
343 * will error out if AVCodecContext.sample_fmt isn't set.
345 if (context->request_sample_fmt == AV_SAMPLE_FMT_NONE)
347 context->request_sample_fmt = codec->sample_fmts[0];
349 context->sample_fmt = context->request_sample_fmt;
354 * Registers work objects, by adding the work object to a liked list.
355 * @param w Handle to hb_work_object_t to register.
357 void hb_register( hb_work_object_t * w )
359 w->next = hb_objects;
360 hb_objects = w;
363 void (*hb_log_callback)(const char* message);
364 static void redirect_thread_func(void *);
366 #if defined( SYS_MINGW )
367 #define pipe(phandles) _pipe (phandles, 4096, _O_BINARY)
368 #endif
371 * Registers the given function as a logger. All logs will be passed to it.
372 * @param log_cb The function to register as a logger.
374 void hb_register_logger( void (*log_cb)(const char* message) )
376 hb_log_callback = log_cb;
377 hb_thread_init("ioredirect", redirect_thread_func, NULL, HB_NORMAL_PRIORITY);
380 void hb_log_level_set(hb_handle_t *h, int level)
382 global_verbosity_level = level;
385 void hb_update_poll(hb_handle_t *h)
387 uint64_t date;
389 hb_log( "hb_update_poll: checking for updates" );
390 date = hb_get_date();
391 h->update_thread = hb_update_init( &h->build, h->version );
393 for( ;; )
395 if (h->update_thread == 0)
397 // Closed by thread_func
398 break;
400 if (hb_thread_has_exited(h->update_thread))
402 /* Immediate success or failure */
403 hb_thread_close( &h->update_thread );
404 break;
406 if (hb_get_date() > date + 1000)
408 /* Still nothing after one second. Connection problem,
409 let the thread die */
410 hb_log( "hb_update_poll: connection problem, not waiting for "
411 "update_thread" );
412 break;
414 hb_snooze( 500 );
419 * libhb initialization routine.
420 * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
421 * @param update_check signals libhb to check for updated version from HandBrake website.
422 * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
424 hb_handle_t * hb_init( int verbose, int update_check )
426 hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
428 /* See hb_deep_log() and hb_log() in common.c */
429 hb_log_level_set(h, verbose);
431 h->id = hb_instance_counter++;
433 /* Check for an update on the website if asked to */
434 h->build = -1;
436 /* Initialize opaque for PowerManagement purposes */
437 h->system_sleep_opaque = hb_system_sleep_opaque_init();
439 if( update_check )
441 hb_update_poll(h);
444 h->title_set.list_title = hb_list_init();
445 h->jobs = hb_list_init();
447 h->state_lock = hb_lock_init();
448 h->state.state = HB_STATE_IDLE;
450 h->pause_lock = hb_lock_init();
452 h->interjob = calloc( sizeof( hb_interjob_t ), 1 );
454 /* Start library thread */
455 hb_log( "hb_init: starting libhb thread" );
456 h->die = 0;
457 h->main_thread = hb_thread_init( "libhb", thread_func, h,
458 HB_NORMAL_PRIORITY );
460 return h;
464 * Returns current version of libhb.
465 * @param h Handle to hb_handle_t.
466 * @return character array of version number.
468 char * hb_get_version( hb_handle_t * h )
470 return HB_PROJECT_VERSION;
474 * Returns current build of libhb.
475 * @param h Handle to hb_handle_t.
476 * @return character array of build number.
478 int hb_get_build( hb_handle_t * h )
480 return HB_PROJECT_BUILD;
484 * Checks for needed update.
485 * @param h Handle to hb_handle_t.
486 * @param version Pointer to handle where version will be copied.
487 * @return update indicator.
489 int hb_check_update( hb_handle_t * h, char ** version )
491 *version = ( h->build < 0 ) ? NULL : h->version;
492 return h->build;
496 * Deletes current previews associated with titles
497 * @param h Handle to hb_handle_t
499 void hb_remove_previews( hb_handle_t * h )
501 char filename[1024];
502 char dirname[1024];
503 hb_title_t * title;
504 int i, count, len;
505 DIR * dir;
506 struct dirent * entry;
508 memset( dirname, 0, 1024 );
509 hb_get_temporary_directory( dirname );
510 dir = opendir( dirname );
511 if (dir == NULL) return;
513 count = hb_list_count( h->title_set.list_title );
514 while( ( entry = readdir( dir ) ) )
516 if( entry->d_name[0] == '.' )
518 continue;
520 for( i = 0; i < count; i++ )
522 title = hb_list_item( h->title_set.list_title, i );
523 len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
524 if (strncmp(entry->d_name, filename, len) == 0)
526 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
527 unlink( filename );
528 break;
532 closedir( dir );
536 * Initializes a scan of the by calling hb_scan_init
537 * @param h Handle to hb_handle_t
538 * @param path location of VIDEO_TS folder.
539 * @param title_index Desired title to scan. 0 for all titles.
540 * @param preview_count Number of preview images to generate.
541 * @param store_previews Whether or not to write previews to disk.
543 void hb_scan( hb_handle_t * h, const char * path, int title_index,
544 int preview_count, int store_previews, uint64_t min_duration )
546 hb_title_t * title;
548 // Check if scanning is necessary.
549 if (!strcmp(h->title_set.path, path))
551 // Current title_set path matches requested path.
552 // Check if the requested title has already been scanned.
553 int ii;
554 for (ii = 0; ii < hb_list_count(h->title_set.list_title); ii++)
556 title = hb_list_item(h->title_set.list_title, ii);
557 if (title->index == title_index)
559 // Title has already been scanned.
560 hb_lock( h->state_lock );
561 h->state.state = HB_STATE_SCANDONE;
562 hb_unlock( h->state_lock );
563 return;
568 h->scan_die = 0;
570 /* Clean up from previous scan */
571 hb_remove_previews( h );
572 while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
574 hb_list_rem( h->title_set.list_title, title );
575 hb_title_close( &title );
578 /* Print CPU info here so that it's in all scan and encode logs */
579 const char *cpu_name = hb_get_cpu_name();
580 const char *cpu_type = hb_get_cpu_platform_name();
581 hb_log("CPU: %s", cpu_name != NULL ? cpu_name : "");
582 if (cpu_type != NULL)
584 hb_log(" - %s", cpu_type);
586 hb_log(" - logical processor count: %d", hb_get_cpu_count());
588 /* Print OpenCL info here so that it's in all scan and encode logs */
589 hb_opencl_info_print();
591 #ifdef USE_QSV
592 /* Print QSV info here so that it's in all scan and encode logs */
593 hb_qsv_info_print();
594 #endif
596 hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
597 h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
598 &h->title_set, preview_count,
599 store_previews, min_duration );
603 * Returns the list of titles found.
604 * @param h Handle to hb_handle_t
605 * @return Handle to hb_list_t of the title list.
607 hb_list_t * hb_get_titles( hb_handle_t * h )
609 return h->title_set.list_title;
612 hb_title_set_t * hb_get_title_set( hb_handle_t * h )
614 return &h->title_set;
617 int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf )
619 FILE * file;
620 char filename[1024];
622 hb_get_tempory_filename( h, filename, "%d_%d_%d",
623 hb_get_instance_id(h), title, preview );
625 file = hb_fopen(filename, "wb");
626 if( !file )
628 hb_error( "hb_save_preview: fopen failed (%s)", filename );
629 return -1;
632 int pp, hh;
633 for( pp = 0; pp < 3; pp++ )
635 uint8_t *data = buf->plane[pp].data;
636 int stride = buf->plane[pp].stride;
637 int w = buf->plane[pp].width;
638 int h = buf->plane[pp].height;
640 for( hh = 0; hh < h; hh++ )
642 fwrite( data, w, 1, file );
643 data += stride;
646 fclose( file );
647 return 0;
650 hb_buffer_t * hb_read_preview(hb_handle_t * h, hb_title_t *title, int preview)
652 FILE * file;
653 char filename[1024];
655 hb_get_tempory_filename(h, filename, "%d_%d_%d",
656 hb_get_instance_id(h), title->index, preview);
658 file = hb_fopen(filename, "rb");
659 if (!file)
661 hb_error( "hb_read_preview: fopen failed (%s)", filename );
662 return NULL;
665 hb_buffer_t * buf;
666 buf = hb_frame_buffer_init(AV_PIX_FMT_YUV420P,
667 title->geometry.width, title->geometry.height);
669 int pp, hh;
670 for (pp = 0; pp < 3; pp++)
672 uint8_t *data = buf->plane[pp].data;
673 int stride = buf->plane[pp].stride;
674 int w = buf->plane[pp].width;
675 int h = buf->plane[pp].height;
677 for (hh = 0; hh < h; hh++)
679 fread(data, w, 1, file);
680 data += stride;
683 fclose(file);
685 return buf;
688 hb_image_t* hb_get_preview2(hb_handle_t * h, int title_idx, int picture,
689 hb_geometry_settings_t *geo, int deinterlace)
691 char filename[1024];
692 hb_buffer_t * in_buf, * deint_buf = NULL, * preview_buf;
693 uint32_t swsflags;
694 AVPicture pic_in, pic_preview, pic_deint, pic_crop;
695 struct SwsContext * context;
697 int width = geo->geometry.width *
698 geo->geometry.par.num / geo->geometry.par.den;
699 int height = geo->geometry.height;
701 swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
703 preview_buf = hb_frame_buffer_init(AV_PIX_FMT_RGB32, width, height);
704 // fill in AVPicture
705 hb_avpicture_fill( &pic_preview, preview_buf );
708 memset( filename, 0, 1024 );
710 hb_title_t * title;
711 title = hb_find_title_by_index(h, title_idx);
712 if (title == NULL)
714 hb_error( "hb_get_preview2: invalid title (%d)", title_idx );
715 goto fail;
718 in_buf = hb_read_preview( h, title, picture );
719 if ( in_buf == NULL )
721 goto fail;
724 hb_avpicture_fill( &pic_in, in_buf );
726 if (deinterlace)
728 // Deinterlace and crop
729 deint_buf = hb_frame_buffer_init( AV_PIX_FMT_YUV420P,
730 title->geometry.width, title->geometry.height );
731 hb_deinterlace(deint_buf, in_buf);
732 hb_avpicture_fill( &pic_deint, deint_buf );
734 av_picture_crop(&pic_crop, &pic_deint, AV_PIX_FMT_YUV420P,
735 geo->crop[0], geo->crop[2] );
737 else
739 // Crop
740 av_picture_crop(&pic_crop, &pic_in, AV_PIX_FMT_YUV420P,
741 geo->crop[0], geo->crop[2] );
744 // Get scaling context
745 context = hb_sws_get_context(
746 title->geometry.width - (geo->crop[2] + geo->crop[3]),
747 title->geometry.height - (geo->crop[0] + geo->crop[1]),
748 AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGB32, swsflags);
750 // Scale
751 sws_scale(context,
752 (const uint8_t* const *)pic_crop.data, pic_crop.linesize,
753 0, title->geometry.height - (geo->crop[0] + geo->crop[1]),
754 pic_preview.data, pic_preview.linesize);
756 // Free context
757 sws_freeContext( context );
759 hb_image_t *image = hb_buffer_to_image(preview_buf);
761 // Clean up
762 hb_buffer_close( &in_buf );
763 hb_buffer_close( &deint_buf );
764 hb_buffer_close( &preview_buf );
766 return image;
768 fail:
770 image = hb_image_init(AV_PIX_FMT_RGB32, width, height);
771 return image;
775 * Analyzes a frame to detect interlacing artifacts
776 * and returns true if interlacing (combing) is found.
778 * Code taken from Thomas Oestreich's 32detect filter
779 * in the Transcode project, with minor formatting changes.
781 * @param buf An hb_buffer structure holding valid frame data
782 * @param width The frame's width in pixels
783 * @param height The frame's height in pixels
784 * @param color_equal Sensitivity for detecting similar colors
785 * @param color_diff Sensitivity for detecting different colors
786 * @param threshold Sensitivity for flagging planes as combed
787 * @param prog_equal Sensitivity for detecting similar colors on progressive frames
788 * @param prog_diff Sensitivity for detecting different colors on progressive frames
789 * @param prog_threshold Sensitivity for flagging progressive frames as combed
791 int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold )
793 int j, k, n, off, cc_1, cc_2, cc[3];
794 // int flag[3] ; // debugging flag
795 uint16_t s1, s2, s3, s4;
796 cc_1 = 0; cc_2 = 0;
798 if ( buf->s.flags & 16 )
800 /* Frame is progressive, be more discerning. */
801 color_diff = prog_diff;
802 color_equal = prog_equal;
803 threshold = prog_threshold;
806 /* One pas for Y, one pass for Cb, one pass for Cr */
807 for( k = 0; k < 3; k++ )
809 uint8_t * data = buf->plane[k].data;
810 int width = buf->plane[k].width;
811 int stride = buf->plane[k].stride;
812 int height = buf->plane[k].height;
814 for( j = 0; j < width; ++j )
816 off = 0;
818 for( n = 0; n < ( height - 4 ); n = n + 2 )
820 /* Look at groups of 4 sequential horizontal lines */
821 s1 = ( ( data )[ off + j ] & 0xff );
822 s2 = ( ( data )[ off + j + stride ] & 0xff );
823 s3 = ( ( data )[ off + j + 2 * stride ] & 0xff );
824 s4 = ( ( data )[ off + j + 3 * stride ] & 0xff );
826 /* Note if the 1st and 2nd lines are more different in
827 color than the 1st and 3rd lines are similar in color.*/
828 if ( ( abs( s1 - s3 ) < color_equal ) &&
829 ( abs( s1 - s2 ) > color_diff ) )
830 ++cc_1;
832 /* Note if the 2nd and 3rd lines are more different in
833 color than the 2nd and 4th lines are similar in color.*/
834 if ( ( abs( s2 - s4 ) < color_equal ) &&
835 ( abs( s2 - s3 ) > color_diff) )
836 ++cc_2;
838 /* Now move down 2 horizontal lines before starting over.*/
839 off += 2 * stride;
843 // compare results
844 /* The final cc score for a plane is the percentage of combed pixels it contains.
845 Because sensitivity goes down to hundreths of a percent, multiply by 1000
846 so it will be easy to compare against the threhold value which is an integer. */
847 cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
851 /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
852 int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
854 /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
855 if( average_cc > threshold )
857 #if 0
858 hb_log("Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
859 #endif
860 return 1;
863 #if 0
864 hb_log("SKIPPED Average %i combed (Threshold %i) %i/%i/%i | PTS: %"PRId64" (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
865 #endif
867 /* Reaching this point means no combing detected. */
868 return 0;
873 * Calculates destination width and height for anamorphic content
875 * Returns calculated geometry
876 * @param source_geometry - Pointer to source geometry info
877 * @param geometry - Pointer to requested destination parameters
879 void hb_set_anamorphic_size2(hb_geometry_t *src_geo,
880 hb_geometry_settings_t *geo,
881 hb_geometry_t *result)
883 hb_rational_t in_par, out_par;
884 int keep_display_aspect = !!(geo->keep & HB_KEEP_DISPLAY_ASPECT);
885 int keep_height = !!(geo->keep & HB_KEEP_HEIGHT);
887 /* Set up some variables to make the math easier to follow. */
888 int cropped_width = src_geo->width - geo->crop[2] - geo->crop[3];
889 int cropped_height = src_geo->height - geo->crop[0] - geo->crop[1];
890 double storage_aspect = (double)cropped_width / cropped_height;
891 int mod = geo->modulus ? EVEN(geo->modulus) : 2;
893 // Sanitize PAR
894 if (geo->geometry.par.num == 0 || geo->geometry.par.den == 0)
896 geo->geometry.par.num = geo->geometry.par.den = 1;
898 if (src_geo->par.num == 0 || src_geo->par.den == 0)
900 src_geo->par.num = src_geo->par.den = 1;
903 // Use 64 bits to avoid overflow till the final hb_reduce() call
904 hb_reduce(&in_par.num, &in_par.den,
905 geo->geometry.par.num, geo->geometry.par.den);
906 int64_t dst_par_num = in_par.num;
907 int64_t dst_par_den = in_par.den;
909 hb_rational_t src_par = src_geo->par;
911 /* If a source was really NTSC or PAL and the user specified ITU PAR
912 values, replace the standard PAR values with the ITU broadcast ones. */
913 if (src_geo->width == 720 && geo->itu_par)
915 // convert aspect to a scaled integer so we can test for 16:9 & 4:3
916 // aspect ratios ignoring insignificant differences in the LSBs of
917 // the floating point representation.
918 int iaspect = src_geo->width * src_par.num * 9. /
919 (src_geo->height * src_par.den);
921 /* Handle ITU PARs */
922 if (src_geo->height == 480)
924 /* It's NTSC */
925 if (iaspect == 16)
927 /* It's widescreen */
928 dst_par_num = 40;
929 dst_par_den = 33;
931 else if (iaspect == 12)
933 /* It's 4:3 */
934 dst_par_num = 10;
935 dst_par_den = 11;
938 else if (src_geo->height == 576)
940 /* It's PAL */
941 if (iaspect == 16)
943 /* It's widescreen */
944 dst_par_num = 16;
945 dst_par_den = 11;
947 else if (iaspect == 12)
949 /* It's 4:3 */
950 dst_par_num = 12;
951 dst_par_den = 11;
957 3 different ways of deciding output dimensions:
958 - 1: Strict anamorphic, preserve source dimensions
959 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
960 - 3: Power user anamorphic, specify everything
962 int width, height;
963 int maxWidth, maxHeight;
965 maxWidth = MULTIPLE_MOD_DOWN(geo->maxWidth, mod);
966 maxHeight = MULTIPLE_MOD_DOWN(geo->maxHeight, mod);
967 if (maxWidth && maxWidth < 32)
968 maxWidth = 32;
969 if (maxHeight && maxHeight < 32)
970 maxHeight = 32;
972 switch (geo->mode)
974 case HB_ANAMORPHIC_NONE:
976 double par, cropped_sar, dar;
977 par = (double)src_geo->par.num / src_geo->par.den;
978 cropped_sar = (double)cropped_width / cropped_height;
979 dar = par * cropped_sar;
981 /* "None" anamorphic. a.k.a. non-anamorphic
982 * - Uses mod-compliant dimensions, set by user
983 * - Allows users to set the either width *or* height
985 if (keep_display_aspect)
987 if (!keep_height)
989 width = MULTIPLE_MOD_UP(geo->geometry.width, mod);
990 height = MULTIPLE_MOD(width / dar, mod);
992 else
994 height = MULTIPLE_MOD_UP(geo->geometry.height, mod);
995 width = MULTIPLE_MOD(height * dar, mod);
998 else
1000 width = MULTIPLE_MOD_UP(geo->geometry.width, mod);
1001 height = MULTIPLE_MOD_UP(geo->geometry.height, mod);
1003 if (maxWidth && (width > maxWidth))
1005 width = maxWidth;
1006 if (keep_display_aspect)
1008 height = MULTIPLE_MOD(width / dar, mod);
1011 if (maxHeight && (height > maxHeight))
1013 height = maxHeight;
1014 if (keep_display_aspect)
1016 width = MULTIPLE_MOD(height * dar, mod);
1019 dst_par_num = dst_par_den = 1;
1020 } break;
1022 default:
1023 case HB_ANAMORPHIC_STRICT:
1025 /* "Strict" anamorphic.
1026 * - Uses mod2-compliant dimensions,
1027 * - Forces title - crop dimensions
1029 width = MULTIPLE_MOD_UP(cropped_width, 2);
1030 height = MULTIPLE_MOD_UP(cropped_height, 2);
1032 /* Adjust the output PAR for new width/height
1033 * Film AR is the source display width / cropped source height.
1034 * Output display width is the output height * film AR.
1035 * Output PAR is the output display width / output storage width.
1037 * i.e.
1038 * source_display_width = cropped_width * source PAR
1039 * AR = source_display_width / cropped_height;
1040 * output_display_width = height * AR;
1041 * par = output_display_width / width;
1043 * When these terms are reduced, you get the following...
1045 dst_par_num = (int64_t)height * cropped_width * src_par.num;
1046 dst_par_den = (int64_t)width * cropped_height * src_par.den;
1047 } break;
1049 case HB_ANAMORPHIC_LOOSE:
1051 /* "Loose" anamorphic.
1052 * - Uses mod-compliant dimensions, set by user
1053 * - Allows users to set the either width *or* height
1055 if (!keep_height)
1057 width = MULTIPLE_MOD_UP(geo->geometry.width, mod);
1058 height = MULTIPLE_MOD_UP(width / storage_aspect + 0.5, mod);
1060 else
1062 height = MULTIPLE_MOD_UP(geo->geometry.height, mod);
1063 width = MULTIPLE_MOD_UP(height * storage_aspect + 0.5, mod);
1066 if (maxWidth && (maxWidth < width))
1068 width = maxWidth;
1069 height = MULTIPLE_MOD(width / storage_aspect + 0.5, mod);
1072 if (maxHeight && (maxHeight < height))
1074 height = maxHeight;
1075 width = MULTIPLE_MOD(height * storage_aspect + 0.5, mod);
1078 /* Adjust the output PAR for new width/height
1079 See comment in HB_ANAMORPHIC_STRICT */
1080 dst_par_num = (int64_t)height * cropped_width * src_par.num;
1081 dst_par_den = (int64_t)width * cropped_height * src_par.den;
1082 } break;
1084 case HB_ANAMORPHIC_CUSTOM:
1086 /* Anamorphic 3: Power User Jamboree
1087 - Set everything based on specified values */
1089 /* Use specified storage dimensions */
1090 storage_aspect = (double)geo->geometry.width / geo->geometry.height;
1092 /* Time to get picture dimensions that divide cleanly.*/
1093 width = MULTIPLE_MOD_UP(geo->geometry.width, mod);
1094 height = MULTIPLE_MOD_UP(geo->geometry.height, mod);
1096 /* Bind to max dimensions */
1097 if (maxWidth && width > maxWidth)
1099 width = maxWidth;
1100 // If we are keeping the display aspect, then we are going
1101 // to be modifying the PAR anyway. So it's preferred
1102 // to let the width/height stray some from the original
1103 // requested storage aspect.
1105 // But otherwise, PAR and DAR will change the least
1106 // if we stay as close as possible to the requested
1107 // storage aspect.
1108 if (!keep_display_aspect &&
1109 (maxHeight == 0 || height < maxHeight))
1111 height = width / storage_aspect + 0.5;
1112 height = MULTIPLE_MOD(height, mod);
1115 if (maxHeight && height > maxHeight)
1117 height = maxHeight;
1118 // Ditto, see comment above
1119 if (!keep_display_aspect &&
1120 (maxWidth == 0 || width < maxWidth))
1122 width = height * storage_aspect + 0.5;
1123 width = MULTIPLE_MOD(width, mod);
1126 if (keep_display_aspect)
1128 /* We can ignore the possibility of a PAR change
1129 * Adjust the output PAR for new width/height
1130 * See comment in HB_ANAMORPHIC_STRICT
1132 dst_par_num = (int64_t)height * cropped_width *
1133 src_par.num;
1134 dst_par_den = (int64_t)width * cropped_height *
1135 src_par.den;
1137 else
1139 /* If the dimensions were changed by the modulus
1140 * or by maxWidth/maxHeight, we also change the
1141 * output PAR so that the DAR is unchanged.
1143 * PAR is the requested output display width / storage width
1144 * requested output display width is the original
1145 * requested width * original requested PAR
1147 dst_par_num = geo->geometry.width * dst_par_num;
1148 dst_par_den = width * dst_par_den;
1150 } break;
1153 /* Pass the results back to the caller */
1154 result->width = width;
1155 result->height = height;
1157 /* While x264 is smart enough to reduce fractions on its own, libavcodec
1158 * needs some help with the math, so lose superfluous factors. */
1159 hb_limit_rational64(&dst_par_num, &dst_par_den,
1160 dst_par_num, dst_par_den, 65535);
1162 // If the user is directling updating PAR, don't override his values.
1163 // I.e. don't even reduce the values.
1164 hb_reduce(&out_par.num, &out_par.den, dst_par_num, dst_par_den);
1165 if (geo->mode == HB_ANAMORPHIC_CUSTOM && !keep_display_aspect &&
1166 out_par.num == in_par.num && out_par.den == in_par.den)
1168 result->par.num = geo->geometry.par.num;
1169 result->par.den = geo->geometry.par.den;
1171 else
1173 hb_reduce(&result->par.num, &result->par.den, dst_par_num, dst_par_den);
1178 * Add a filter to a jobs filter list
1180 * @param job Handle to hb_job_t
1181 * @param settings to give the filter
1183 void hb_add_filter( hb_job_t * job, hb_filter_object_t * filter, const char * settings_in )
1185 char * settings = NULL;
1187 if ( settings_in != NULL )
1189 settings = strdup( settings_in );
1191 filter->settings = settings;
1192 if( filter->enforce_order )
1194 // Find the position in the filter chain this filter belongs in
1195 int i;
1196 for( i = 0; i < hb_list_count( job->list_filter ); i++ )
1198 hb_filter_object_t * f = hb_list_item( job->list_filter, i );
1199 if( f->id > filter->id )
1201 hb_list_insert( job->list_filter, i, filter );
1202 return;
1204 else if( f->id == filter->id )
1206 // Don't allow the same filter to be added twice
1207 hb_filter_close( &filter );
1208 return;
1212 // No position found or order not enforced for this filter
1213 hb_list_add( job->list_filter, filter );
1217 * Returns the number of jobs in the queue.
1218 * @param h Handle to hb_handle_t.
1219 * @return Number of jobs.
1221 int hb_count( hb_handle_t * h )
1223 return hb_list_count( h->jobs );
1227 * Returns handle to job at index i within the job list.
1228 * @param h Handle to hb_handle_t.
1229 * @param i Index of job.
1230 * @returns Handle to hb_job_t of desired job.
1232 hb_job_t * hb_job( hb_handle_t * h, int i )
1234 return hb_list_item( h->jobs, i );
1237 hb_job_t * hb_current_job( hb_handle_t * h )
1239 return( h->current_job );
1243 * Adds a job to the job list.
1244 * @param h Handle to hb_handle_t.
1245 * @param job Handle to hb_job_t.
1247 static void hb_add_internal( hb_handle_t * h, hb_job_t * job, hb_list_t *list_pass )
1249 hb_job_t * job_copy;
1250 hb_audio_t * audio;
1251 hb_subtitle_t * subtitle;
1252 int i;
1253 char audio_lang[4];
1255 /* Copy the job */
1256 job_copy = calloc( sizeof( hb_job_t ), 1 );
1257 memcpy( job_copy, job, sizeof( hb_job_t ) );
1259 /* If we're doing Foreign Audio Search, copy all subtitles matching the
1260 * first audio track language we find in the audio list.
1262 * Otherwise, copy all subtitles found in the input job (which can be
1263 * manually selected by the user, or added after the Foreign Audio
1264 * Search pass). */
1265 memset( audio_lang, 0, sizeof( audio_lang ) );
1267 if( job->indepth_scan )
1270 /* Find the first audio language that is being encoded, then add all the
1271 * matching subtitles for that language. */
1272 for( i = 0; i < hb_list_count( job->list_audio ); i++ )
1274 if( ( audio = hb_list_item( job->list_audio, i ) ) )
1276 strncpy( audio_lang, audio->config.lang.iso639_2, sizeof( audio_lang ) );
1277 break;
1282 * If doing a subtitle scan then add all the matching subtitles for this
1283 * language.
1285 job_copy->list_subtitle = hb_list_init();
1287 for( i = 0; i < hb_list_count( job->title->list_subtitle ); i++ )
1289 subtitle = hb_list_item( job->title->list_subtitle, i );
1290 if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
1291 hb_subtitle_can_force( subtitle->source ) )
1293 /* Matched subtitle language with audio language, so add this to
1294 * our list to scan.
1296 * We will update the subtitle list on the next pass later, after
1297 * the subtitle scan pass has completed. */
1298 hb_list_add( job_copy->list_subtitle,
1299 hb_subtitle_copy( subtitle ) );
1303 else
1305 /* Copy all subtitles from the input job to title_copy/job_copy. */
1306 job_copy->list_subtitle = hb_subtitle_list_copy( job->list_subtitle );
1309 job_copy->list_chapter = hb_chapter_list_copy( job->list_chapter );
1310 job_copy->list_audio = hb_audio_list_copy( job->list_audio );
1311 job_copy->list_attachment = hb_attachment_list_copy( job->list_attachment );
1312 job_copy->metadata = hb_metadata_copy( job->metadata );
1314 if (job->encoder_preset != NULL)
1315 job_copy->encoder_preset = strdup(job->encoder_preset);
1316 if (job->encoder_tune != NULL)
1317 job_copy->encoder_tune = strdup(job->encoder_tune);
1318 if (job->encoder_options != NULL)
1319 job_copy->encoder_options = strdup(job->encoder_options);
1320 if (job->encoder_profile != NULL)
1321 job_copy->encoder_profile = strdup(job->encoder_profile);
1322 if (job->encoder_level != NULL)
1323 job_copy->encoder_level = strdup(job->encoder_level);
1324 if (job->file != NULL)
1325 job_copy->file = strdup(job->file);
1327 job_copy->h = h;
1329 /* Copy the job filter list */
1330 job_copy->list_filter = hb_filter_list_copy( job->list_filter );
1332 /* Add the job to the list */
1333 hb_list_add( list_pass, job_copy );
1336 hb_job_t* hb_job_copy(hb_job_t * job)
1338 hb_job_t * job_copy;
1340 /* Copy the job */
1341 job_copy = calloc( sizeof( hb_job_t ), 1 );
1342 if (job_copy == NULL)
1343 return NULL;
1345 if (job->json != NULL)
1347 // JSON jobs should only have the json string set.
1348 job_copy->json = strdup(job->json);
1349 return job_copy;
1351 memcpy( job_copy, job, sizeof( hb_job_t ) );
1353 job_copy->list_subtitle = hb_subtitle_list_copy( job->list_subtitle );
1354 job_copy->list_chapter = hb_chapter_list_copy( job->list_chapter );
1355 job_copy->list_audio = hb_audio_list_copy( job->list_audio );
1356 job_copy->list_attachment = hb_attachment_list_copy( job->list_attachment );
1357 job_copy->metadata = hb_metadata_copy( job->metadata );
1359 if (job->encoder_preset != NULL)
1360 job_copy->encoder_preset = strdup(job->encoder_preset);
1361 if (job->encoder_tune != NULL)
1362 job_copy->encoder_tune = strdup(job->encoder_tune);
1363 if (job->encoder_options != NULL)
1364 job_copy->encoder_options = strdup(job->encoder_options);
1365 if (job->encoder_profile != NULL)
1366 job_copy->encoder_profile = strdup(job->encoder_profile);
1367 if (job->encoder_level != NULL)
1368 job_copy->encoder_level = strdup(job->encoder_level);
1369 if (job->file != NULL)
1370 job_copy->file = strdup(job->file);
1372 job_copy->list_filter = hb_filter_list_copy( job->list_filter );
1374 return job_copy;
1377 void hb_add( hb_handle_t * h, hb_job_t * job )
1379 hb_job_t *job_copy = hb_job_copy(job);
1380 job_copy->h = h;
1381 hb_list_add(h->jobs, job_copy);
1384 void hb_job_setup_passes(hb_handle_t * h, hb_job_t * job, hb_list_t * list_pass)
1386 if (job->vquality >= 0)
1388 job->twopass = 0;
1390 if (job->indepth_scan)
1392 hb_deep_log(2, "Adding subtitle scan pass");
1393 job->pass_id = HB_PASS_SUBTITLE;
1394 hb_add_internal(h, job, list_pass);
1395 job->indepth_scan = 0;
1397 if (job->twopass)
1399 hb_deep_log(2, "Adding two-pass encode");
1400 job->pass_id = HB_PASS_ENCODE_1ST;
1401 hb_add_internal(h, job, list_pass);
1402 job->pass_id = HB_PASS_ENCODE_2ND;
1403 hb_add_internal(h, job, list_pass);
1405 else
1407 job->pass_id = HB_PASS_ENCODE;
1408 hb_add_internal(h, job, list_pass);
1413 * Removes a job from the job list.
1414 * @param h Handle to hb_handle_t.
1415 * @param job Handle to hb_job_t.
1417 void hb_rem( hb_handle_t * h, hb_job_t * job )
1419 hb_list_rem( h->jobs, job );
1423 * Starts the conversion process.
1424 * Sets state to HB_STATE_WORKING.
1425 * calls hb_work_init, to launch work thread. Stores handle to work thread.
1426 * @param h Handle to hb_handle_t.
1428 void hb_start( hb_handle_t * h )
1430 hb_lock( h->state_lock );
1431 h->state.state = HB_STATE_WORKING;
1432 #define p h->state.param.working
1433 p.progress = 0.0;
1434 p.rate_cur = 0.0;
1435 p.rate_avg = 0.0;
1436 p.hours = -1;
1437 p.minutes = -1;
1438 p.seconds = -1;
1439 p.sequence_id = 0;
1440 #undef p
1441 hb_unlock( h->state_lock );
1443 h->paused = 0;
1445 h->work_die = 0;
1446 h->work_error = HB_ERROR_NONE;
1447 h->work_thread = hb_work_init( h->jobs, &h->work_die, &h->work_error, &h->current_job );
1451 * Pauses the conversion process.
1452 * @param h Handle to hb_handle_t.
1454 void hb_pause( hb_handle_t * h )
1456 if( !h->paused )
1458 hb_lock( h->pause_lock );
1459 h->paused = 1;
1461 hb_current_job( h )->st_pause_date = hb_get_date();
1463 hb_lock( h->state_lock );
1464 h->state.state = HB_STATE_PAUSED;
1465 hb_unlock( h->state_lock );
1470 * Resumes the conversion process.
1471 * @param h Handle to hb_handle_t.
1473 void hb_resume( hb_handle_t * h )
1475 if( h->paused )
1477 #define job hb_current_job( h )
1478 if( job->st_pause_date != -1 )
1480 job->st_paused += hb_get_date() - job->st_pause_date;
1482 #undef job
1484 hb_unlock( h->pause_lock );
1485 h->paused = 0;
1490 * Stops the conversion process.
1491 * @param h Handle to hb_handle_t.
1493 void hb_stop( hb_handle_t * h )
1495 h->work_die = 1;
1496 hb_resume( h );
1500 * Stops the conversion process.
1501 * @param h Handle to hb_handle_t.
1503 void hb_scan_stop( hb_handle_t * h )
1505 h->scan_die = 1;
1506 hb_resume( h );
1510 * Returns the state of the conversion process.
1511 * @param h Handle to hb_handle_t.
1512 * @param s Handle to hb_state_t which to copy the state data.
1514 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1516 hb_lock( h->state_lock );
1518 memcpy( s, &h->state, sizeof( hb_state_t ) );
1519 if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1520 h->state.state = HB_STATE_IDLE;
1522 hb_unlock( h->state_lock );
1525 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1527 hb_lock( h->state_lock );
1529 memcpy( s, &h->state, sizeof( hb_state_t ) );
1531 hb_unlock( h->state_lock );
1535 * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init.
1536 * @param _h Pointer to handle to hb_handle_t.
1538 void hb_close( hb_handle_t ** _h )
1540 hb_handle_t * h = *_h;
1541 hb_title_t * title;
1543 h->die = 1;
1545 hb_thread_close( &h->main_thread );
1547 while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
1549 hb_list_rem( h->title_set.list_title, title );
1550 hb_title_close( &title );
1552 hb_list_close( &h->title_set.list_title );
1554 hb_list_close( &h->jobs );
1555 hb_lock_close( &h->state_lock );
1556 hb_lock_close( &h->pause_lock );
1558 hb_system_sleep_opaque_close(&h->system_sleep_opaque);
1560 free( h->interjob );
1562 free( h );
1563 *_h = NULL;
1566 int hb_global_init()
1568 int result = 0;
1570 result = hb_platform_init();
1571 if (result < 0)
1573 hb_error("Platform specific initialization failed!");
1574 return -1;
1577 #ifdef USE_QSV
1578 result = hb_qsv_info_init();
1579 if (result < 0)
1581 hb_error("hb_qsv_info_init failed!");
1582 return -1;
1584 #endif
1586 /* libavcodec */
1587 hb_avcodec_init();
1589 /* HB work objects */
1590 hb_register(&hb_muxer);
1591 hb_register(&hb_reader);
1592 hb_register(&hb_sync_video);
1593 hb_register(&hb_sync_audio);
1594 hb_register(&hb_decavcodecv);
1595 hb_register(&hb_decavcodeca);
1596 hb_register(&hb_declpcm);
1597 hb_register(&hb_deccc608);
1598 hb_register(&hb_decpgssub);
1599 hb_register(&hb_decsrtsub);
1600 hb_register(&hb_decssasub);
1601 hb_register(&hb_dectx3gsub);
1602 hb_register(&hb_decutf8sub);
1603 hb_register(&hb_decvobsub);
1604 hb_register(&hb_encvobsub);
1605 hb_register(&hb_encavcodec);
1606 hb_register(&hb_encavcodeca);
1607 #ifdef __APPLE__
1608 hb_register(&hb_encca_aac);
1609 hb_register(&hb_encca_haac);
1610 #endif
1611 hb_register(&hb_enclame);
1612 hb_register(&hb_enctheora);
1613 hb_register(&hb_encvorbis);
1614 hb_register(&hb_encx264);
1615 #ifdef USE_X265
1616 hb_register(&hb_encx265);
1617 #endif
1618 #ifdef USE_QSV
1619 hb_register(&hb_encqsv);
1620 #endif
1622 hb_common_global_init();
1625 * Initialise buffer pool
1627 hb_buffer_pool_init();
1629 // Initialize the builtin presets hb_dict_t
1630 hb_presets_builtin_init();
1632 return result;
1636 * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1638 void hb_global_close()
1640 char dirname[1024];
1641 DIR * dir;
1642 struct dirent * entry;
1644 hb_presets_free();
1646 /* OpenCL library (dynamically loaded) */
1647 hb_ocl_close();
1649 /* Find and remove temp folder */
1650 memset( dirname, 0, 1024 );
1651 hb_get_temporary_directory( dirname );
1653 dir = opendir( dirname );
1654 if (dir)
1656 while( ( entry = readdir( dir ) ) )
1658 char filename[1024];
1659 if( entry->d_name[0] == '.' )
1661 continue;
1663 memset( filename, 0, 1024 );
1664 snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1665 unlink( filename );
1667 closedir( dir );
1668 rmdir( dirname );
1673 * Monitors the state of the update, scan, and work threads.
1674 * Sets scan done state when scan thread exits.
1675 * Sets work done state when work thread exits.
1676 * @param _h Handle to hb_handle_t
1678 static void thread_func( void * _h )
1680 hb_handle_t * h = (hb_handle_t *) _h;
1681 char dirname[1024];
1683 h->pid = getpid();
1685 /* Create folder for temporary files */
1686 memset( dirname, 0, 1024 );
1687 hb_get_temporary_directory( dirname );
1689 hb_mkdir( dirname );
1691 while( !h->die )
1693 /* In case the check_update thread hangs, it'll die sooner or
1694 later. Then, we join it here */
1695 if( h->update_thread &&
1696 hb_thread_has_exited( h->update_thread ) )
1698 hb_thread_close( &h->update_thread );
1701 /* Check if the scan thread is done */
1702 if( h->scan_thread &&
1703 hb_thread_has_exited( h->scan_thread ) )
1705 hb_thread_close( &h->scan_thread );
1707 if ( h->scan_die )
1709 hb_title_t * title;
1711 hb_remove_previews( h );
1712 while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
1714 hb_list_rem( h->title_set.list_title, title );
1715 hb_title_close( &title );
1718 hb_log( "hb_scan: canceled" );
1720 else
1722 hb_log( "libhb: scan thread found %d valid title(s)",
1723 hb_list_count( h->title_set.list_title ) );
1725 hb_lock( h->state_lock );
1726 h->state.state = HB_STATE_SCANDONE; //originally state.state
1727 hb_unlock( h->state_lock );
1728 /*we increment this sessions scan count by one for the MacGui
1729 to trigger a new source being set */
1730 h->scanCount++;
1733 /* Check if the work thread is done */
1734 if( h->work_thread &&
1735 hb_thread_has_exited( h->work_thread ) )
1737 hb_thread_close( &h->work_thread );
1739 hb_log( "libhb: work result = %d",
1740 h->work_error );
1741 hb_lock( h->state_lock );
1742 h->state.state = HB_STATE_WORKDONE;
1743 h->state.param.workdone.error = h->work_error;
1745 hb_unlock( h->state_lock );
1748 hb_snooze( 50 );
1751 if( h->scan_thread )
1753 hb_scan_stop( h );
1754 hb_thread_close( &h->scan_thread );
1756 if( h->work_thread )
1758 hb_stop( h );
1759 hb_thread_close( &h->work_thread );
1761 hb_remove_previews( h );
1765 * Redirects stderr to the registered callback
1766 * function.
1767 * @param _data Unused.
1769 static void redirect_thread_func(void * _data)
1771 int pfd[2];
1772 pipe(pfd);
1773 #if defined( SYS_MINGW )
1774 // dup2 doesn't work on windows for some stupid reason
1775 stderr->_file = pfd[1];
1776 #else
1777 dup2(pfd[1], /*stderr*/ 2);
1778 #endif
1779 FILE * log_f = fdopen(pfd[0], "rb");
1781 char line_buffer[500];
1782 while(fgets(line_buffer, 500, log_f) != NULL)
1784 hb_log_callback(line_buffer);
1789 * Returns the PID.
1790 * @param h Handle to hb_handle_t
1792 int hb_get_pid( hb_handle_t * h )
1794 return h->pid;
1798 * Returns the id for the given instance.
1799 * @param h Handle to hb_handle_t
1800 * @returns The ID for the given instance
1802 int hb_get_instance_id( hb_handle_t * h )
1804 return h->id;
1808 * Sets the current state.
1809 * @param h Handle to hb_handle_t
1810 * @param s Handle to new hb_state_t
1812 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1814 hb_lock( h->pause_lock );
1815 hb_lock( h->state_lock );
1816 memcpy( &h->state, s, sizeof( hb_state_t ) );
1817 if( h->state.state == HB_STATE_WORKING ||
1818 h->state.state == HB_STATE_SEARCHING )
1820 // Set which job is being worked on
1821 if (h->current_job)
1822 h->state.param.working.sequence_id = h->current_job->sequence_id & 0xFFFFFF;
1823 else
1824 h->state.param.working.sequence_id = 0;
1826 hb_unlock( h->state_lock );
1827 hb_unlock( h->pause_lock );
1830 void hb_set_work_error( hb_handle_t * h, hb_error_code err )
1832 h->work_error = err;
1835 void hb_system_sleep_allow(hb_handle_t *h)
1837 hb_system_sleep_private_enable(h->system_sleep_opaque);
1840 void hb_system_sleep_prevent(hb_handle_t *h)
1842 hb_system_sleep_private_disable(h->system_sleep_opaque);
1845 /* Passes a pointer to persistent data */
1846 hb_interjob_t * hb_interjob_get( hb_handle_t * h )
1848 return h->interjob;