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
18 #include "qsv_common.h"
21 #if defined( SYS_MINGW )
23 #if defined( PTW32_STATIC_LIB )
32 /* The "Check for update" thread */
35 hb_thread_t
* update_thread
;
37 /* This thread's only purpose is to check other threads'
40 hb_thread_t
* main_thread
;
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) */
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
;
59 hb_lock_t
* pause_lock
;
60 /* For MacGui active queue
61 increments each time the scan thread completes*/
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.
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
)
92 hb_hwd_t
* hb_hwd_get_context( hb_handle_t
*h
)
97 static void thread_func( void * );
99 static int ff_lockmgr_cb(void **mutex
, enum AVLockOp op
)
105 *mutex
= hb_lock_init();
107 case AV_LOCK_DESTROY
:
109 hb_lock_close( (hb_lock_t
**)mutex
);
113 hb_lock( (hb_lock_t
*)*mutex
);
115 case AV_LOCK_RELEASE
:
117 hb_unlock( (hb_lock_t
*)*mutex
);
125 void hb_avcodec_init()
127 av_lockmgr_register(ff_lockmgr_cb
);
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
);
139 int hb_avcodec_open(AVCodecContext
*avctx
, AVCodec
*codec
,
140 AVDictionary
**av_opts
, int thread_count
)
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;
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
);
167 int hb_avcodec_close(AVCodecContext
*avctx
)
170 ret
= avcodec_close(avctx
);
175 int hb_avpicture_fill(AVPicture
*pic
, hb_buffer_t
*buf
)
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",
193 static int handle_jpeg(enum AVPixelFormat
*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;
206 hb_sws_get_context(int srcW
, int srcH
, enum AVPixelFormat srcFormat
,
207 int dstW
, int dstH
, enum AVPixelFormat dstFormat
,
210 struct SwsContext
* ctx
;
212 ctx
= sws_alloc_context();
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
240 1 << 16 ); // saturation
242 if (sws_init_context(ctx
, NULL
, NULL
) < 0) {
243 hb_error("Cannot initialize resampling context");
244 sws_freeContext(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
;
258 case HB_AMIXDOWN_NONE
:
261 case HB_AMIXDOWN_MONO
:
262 case HB_AMIXDOWN_LEFT
:
263 case HB_AMIXDOWN_RIGHT
:
264 ff_layout
= AV_CH_LAYOUT_MONO
;
267 case HB_AMIXDOWN_DOLBY
:
268 ff_layout
= AV_CH_LAYOUT_STEREO
;
269 mode
= AV_MATRIX_ENCODING_DOLBY
;
272 case HB_AMIXDOWN_DOLBYPLII
:
273 ff_layout
= AV_CH_LAYOUT_STEREO
;
274 mode
= AV_MATRIX_ENCODING_DPLII
;
277 case HB_AMIXDOWN_STEREO
:
278 ff_layout
= AV_CH_LAYOUT_STEREO
;
281 case HB_AMIXDOWN_5POINT1
:
282 ff_layout
= AV_CH_LAYOUT_5POINT1
;
285 case HB_AMIXDOWN_6POINT1
:
286 ff_layout
= AV_CH_LAYOUT_6POINT1
;
289 case HB_AMIXDOWN_7POINT1
:
290 ff_layout
= AV_CH_LAYOUT_7POINT1
;
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
);
300 ff_layout
= AV_CH_LAYOUT_STEREO
;
301 hb_log("hb_ff_mixdown_xlat: unsupported mixdown %d", hb_mixdown
);
304 if (downmix_mode
!= NULL
)
305 *downmix_mode
= mode
;
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
;
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
;
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)
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
)
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
);
395 if (h
->update_thread
== 0)
397 // Closed by thread_func
400 if (hb_thread_has_exited(h
->update_thread
))
402 /* Immediate success or failure */
403 hb_thread_close( &h
->update_thread
);
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 "
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 */
436 /* Initialize opaque for PowerManagement purposes */
437 h
->system_sleep_opaque
= hb_system_sleep_opaque_init();
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" );
457 h
->main_thread
= hb_thread_init( "libhb", thread_func
, h
,
458 HB_NORMAL_PRIORITY
);
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
;
496 * Deletes current previews associated with titles
497 * @param h Handle to hb_handle_t
499 void hb_remove_previews( hb_handle_t
* h
)
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] == '.' )
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
);
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
)
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.
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
);
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();
592 /* Print QSV info here so that it's in all scan and encode logs */
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
)
622 hb_get_tempory_filename( h
, filename
, "%d_%d_%d",
623 hb_get_instance_id(h
), title
, preview
);
625 file
= hb_fopen(filename
, "wb");
628 hb_error( "hb_save_preview: fopen failed (%s)", filename
);
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
);
650 hb_buffer_t
* hb_read_preview(hb_handle_t
* h
, hb_title_t
*title
, int preview
)
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");
661 hb_error( "hb_read_preview: fopen failed (%s)", filename
);
666 buf
= hb_frame_buffer_init(AV_PIX_FMT_YUV420P
,
667 title
->geometry
.width
, title
->geometry
.height
);
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
);
688 hb_image_t
* hb_get_preview2(hb_handle_t
* h
, int title_idx
, int picture
,
689 hb_geometry_settings_t
*geo
, int deinterlace
)
692 hb_buffer_t
* in_buf
, * deint_buf
= NULL
, * preview_buf
;
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
);
705 hb_avpicture_fill( &pic_preview
, preview_buf
);
708 memset( filename
, 0, 1024 );
711 title
= hb_find_title_by_index(h
, title_idx
);
714 hb_error( "hb_get_preview2: invalid title (%d)", title_idx
);
718 in_buf
= hb_read_preview( h
, title
, picture
);
719 if ( in_buf
== NULL
)
724 hb_avpicture_fill( &pic_in
, in_buf
);
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] );
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
);
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
);
757 sws_freeContext( context
);
759 hb_image_t
*image
= hb_buffer_to_image(preview_buf
);
762 hb_buffer_close( &in_buf
);
763 hb_buffer_close( &deint_buf
);
764 hb_buffer_close( &preview_buf
);
770 image
= hb_image_init(AV_PIX_FMT_RGB32
, width
, height
);
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
;
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
)
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
) )
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
) )
838 /* Now move down 2 horizontal lines before starting over.*/
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
)
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" );
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" );
867 /* Reaching this point means no combing detected. */
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;
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)
927 /* It's widescreen */
931 else if (iaspect
== 12)
938 else if (src_geo
->height
== 576)
943 /* It's widescreen */
947 else if (iaspect
== 12)
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
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)
969 if (maxHeight
&& maxHeight
< 32)
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
)
989 width
= MULTIPLE_MOD_UP(geo
->geometry
.width
, mod
);
990 height
= MULTIPLE_MOD(width
/ dar
, mod
);
994 height
= MULTIPLE_MOD_UP(geo
->geometry
.height
, mod
);
995 width
= MULTIPLE_MOD(height
* dar
, mod
);
1000 width
= MULTIPLE_MOD_UP(geo
->geometry
.width
, mod
);
1001 height
= MULTIPLE_MOD_UP(geo
->geometry
.height
, mod
);
1003 if (maxWidth
&& (width
> maxWidth
))
1006 if (keep_display_aspect
)
1008 height
= MULTIPLE_MOD(width
/ dar
, mod
);
1011 if (maxHeight
&& (height
> maxHeight
))
1014 if (keep_display_aspect
)
1016 width
= MULTIPLE_MOD(height
* dar
, mod
);
1019 dst_par_num
= dst_par_den
= 1;
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.
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
;
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
1057 width
= MULTIPLE_MOD_UP(geo
->geometry
.width
, mod
);
1058 height
= MULTIPLE_MOD_UP(width
/ storage_aspect
+ 0.5, mod
);
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
))
1069 height
= MULTIPLE_MOD(width
/ storage_aspect
+ 0.5, mod
);
1072 if (maxHeight
&& (maxHeight
< height
))
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
;
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
)
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
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
)
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
*
1134 dst_par_den
= (int64_t)width
* cropped_height
*
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
;
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
;
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
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
);
1204 else if( f
->id
== filter
->id
)
1206 // Don't allow the same filter to be added twice
1207 hb_filter_close( &filter
);
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
;
1251 hb_subtitle_t
* subtitle
;
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
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
) );
1282 * If doing a subtitle scan then add all the matching subtitles for this
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
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
) );
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
);
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
;
1341 job_copy
= calloc( sizeof( hb_job_t
), 1 );
1342 if (job_copy
== NULL
)
1345 if (job
->json
!= NULL
)
1347 // JSON jobs should only have the json string set.
1348 job_copy
->json
= strdup(job
->json
);
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
);
1377 void hb_add( hb_handle_t
* h
, hb_job_t
* job
)
1379 hb_job_t
*job_copy
= hb_job_copy(job
);
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)
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;
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
);
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
1441 hb_unlock( h
->state_lock
);
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
)
1458 hb_lock( h
->pause_lock
);
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
)
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
;
1484 hb_unlock( h
->pause_lock
);
1490 * Stops the conversion process.
1491 * @param h Handle to hb_handle_t.
1493 void hb_stop( hb_handle_t
* h
)
1500 * Stops the conversion process.
1501 * @param h Handle to hb_handle_t.
1503 void hb_scan_stop( hb_handle_t
* 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
;
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
);
1566 int hb_global_init()
1570 result
= hb_platform_init();
1573 hb_error("Platform specific initialization failed!");
1578 result
= hb_qsv_info_init();
1581 hb_error("hb_qsv_info_init failed!");
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
);
1608 hb_register(&hb_encca_aac
);
1609 hb_register(&hb_encca_haac
);
1611 hb_register(&hb_enclame
);
1612 hb_register(&hb_enctheora
);
1613 hb_register(&hb_encvorbis
);
1614 hb_register(&hb_encx264
);
1616 hb_register(&hb_encx265
);
1619 hb_register(&hb_encqsv
);
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();
1636 * Cleans up libhb at a process level. Call before the app closes. Removes preview directory.
1638 void hb_global_close()
1642 struct dirent
* entry
;
1646 /* OpenCL library (dynamically loaded) */
1649 /* Find and remove temp folder */
1650 memset( dirname
, 0, 1024 );
1651 hb_get_temporary_directory( dirname
);
1653 dir
= opendir( dirname
);
1656 while( ( entry
= readdir( dir
) ) )
1658 char filename
[1024];
1659 if( entry
->d_name
[0] == '.' )
1663 memset( filename
, 0, 1024 );
1664 snprintf( filename
, 1023, "%s/%s", dirname
, entry
->d_name
);
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
;
1685 /* Create folder for temporary files */
1686 memset( dirname
, 0, 1024 );
1687 hb_get_temporary_directory( dirname
);
1689 hb_mkdir( dirname
);
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
);
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" );
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 */
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",
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
);
1751 if( h
->scan_thread
)
1754 hb_thread_close( &h
->scan_thread
);
1756 if( h
->work_thread
)
1759 hb_thread_close( &h
->work_thread
);
1761 hb_remove_previews( h
);
1765 * Redirects stderr to the registered callback
1767 * @param _data Unused.
1769 static void redirect_thread_func(void * _data
)
1773 #if defined( SYS_MINGW )
1774 // dup2 doesn't work on windows for some stupid reason
1775 stderr
->_file
= pfd
[1];
1777 dup2(pfd
[1], /*stderr*/ 2);
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
);
1790 * @param h Handle to hb_handle_t
1792 int hb_get_pid( hb_handle_t
* h
)
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
)
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
1822 h
->state
.param
.working
.sequence_id
= h
->current_job
->sequence_id
& 0xFFFFFF;
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
)