diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/bd.c | 4 | ||||
-rw-r--r-- | libhb/common.c | 742 | ||||
-rw-r--r-- | libhb/common.h | 101 | ||||
-rw-r--r-- | libhb/decavcodec.c | 2 | ||||
-rw-r--r-- | libhb/decmetadata.c | 114 | ||||
-rw-r--r-- | libhb/decmpeg2.c | 8 | ||||
-rw-r--r-- | libhb/decsrtsub.c | 5 | ||||
-rw-r--r-- | libhb/dvd.c | 4 | ||||
-rw-r--r-- | libhb/dvdnav.c | 4 | ||||
-rw-r--r-- | libhb/hb.c | 326 | ||||
-rw-r--r-- | libhb/hb.h | 18 | ||||
-rw-r--r-- | libhb/internal.h | 4 | ||||
-rw-r--r-- | libhb/muxcommon.c | 9 | ||||
-rw-r--r-- | libhb/muxmkv.c | 72 | ||||
-rw-r--r-- | libhb/muxmp4.c | 73 | ||||
-rw-r--r-- | libhb/reader.c | 20 | ||||
-rw-r--r-- | libhb/rendersub.c | 6 | ||||
-rw-r--r-- | libhb/scan.c | 104 | ||||
-rw-r--r-- | libhb/stream.c | 100 | ||||
-rw-r--r-- | libhb/sync.c | 7 | ||||
-rw-r--r-- | libhb/work.c | 113 |
21 files changed, 1253 insertions, 583 deletions
diff --git a/libhb/bd.c b/libhb/bd.c index 208782674..268cdaab0 100644 --- a/libhb/bd.c +++ b/libhb/bd.c @@ -491,10 +491,12 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration ) /* Chapters */ for ( ii = 0; ii < ti->chapter_count; ii++ ) { + char chapter_title[80]; chapter = calloc( sizeof( hb_chapter_t ), 1 ); chapter->index = ii + 1; - sprintf( chapter->title, "Chapter %d", chapter->index ); + sprintf( chapter_title, "Chapter %d", chapter->index ); + hb_chapter_set_title( chapter, chapter_title ); chapter->duration = ti->chapters[ii].duration; chapter->block_start = ti->chapters[ii].offset; diff --git a/libhb/common.c b/libhb/common.c index 821f17e76..80b526c2a 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -306,13 +306,13 @@ const char* hb_mixdown_get_short_name_from_mixdown(int amixdown) return ""; } -void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title ) +void hb_autopassthru_apply_settings( hb_job_t * job ) { int i, j, already_printed; hb_audio_t * audio; - for( i = 0, already_printed = 0; i < hb_list_count( title->list_audio ); ) + for( i = 0, already_printed = 0; i < hb_list_count( job->list_audio ); ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); if( audio->config.out.codec == HB_ACODEC_AUTO_PASS ) { if( !already_printed ) @@ -327,8 +327,8 @@ void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title ) { hb_log( "Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d", audio->config.out.track ); - hb_list_rem( title->list_audio, audio ); - free( audio ); + hb_list_rem( job->list_audio, audio ); + hb_audio_close( &audio ); continue; } audio->config.out.samplerate = audio->config.in.samplerate; @@ -1157,7 +1157,7 @@ hb_list_t * hb_list_init() ********************************************************************** * Returns the number of items currently in the list *********************************************************************/ -int hb_list_count( hb_list_t * l ) +int hb_list_count( const hb_list_t * l ) { return l->items_count; } @@ -1252,7 +1252,7 @@ void hb_list_rem( hb_list_t * l, void * p ) * Returns item at position i, or NULL if there are not that many * items in the list *********************************************************************/ -void * hb_list_item( hb_list_t * l, int i ) +void * hb_list_item( const hb_list_t * l, int i ) { if( i < 0 || i >= l->items_count ) { @@ -1575,6 +1575,19 @@ void hb_register_error_handler( hb_error_handler_t * handler ) error_handler = handler; } +static void hb_update_str( char **dst, const char *src ) +{ + if ( dst ) + { + free( *dst ); + *dst = NULL; + if ( src ) + { + *dst = strdup( src ); + } + } +} + /********************************************************************** * hb_title_init ********************************************************************** @@ -1592,6 +1605,7 @@ hb_title_t * hb_title_init( char * path, int index ) t->list_chapter = hb_list_init(); t->list_subtitle = hb_list_init(); t->list_attachment = hb_list_init(); + t->metadata = hb_metadata_init(); strcat( t->path, path ); // default to decoding mpeg2 t->video_id = 0xE0; @@ -1616,65 +1630,252 @@ void hb_title_close( hb_title_t ** _t ) hb_subtitle_t * subtitle; hb_attachment_t * attachment; - while( ( audio = hb_list_item( t->list_audio, 0 ) ) ) - { - hb_list_rem( t->list_audio, audio ); - free( audio ); - } - hb_list_close( &t->list_audio ); - while( ( chapter = hb_list_item( t->list_chapter, 0 ) ) ) { hb_list_rem( t->list_chapter, chapter ); - free( chapter ); + hb_chapter_close( &chapter ); } hb_list_close( &t->list_chapter ); + while( ( audio = hb_list_item( t->list_audio, 0 ) ) ) + { + hb_list_rem( t->list_audio, audio ); + hb_audio_close( &audio ); + } + hb_list_close( &t->list_audio ); + while( ( subtitle = hb_list_item( t->list_subtitle, 0 ) ) ) { hb_list_rem( t->list_subtitle, subtitle ); - if ( subtitle->extradata ) - { - free( subtitle->extradata ); - subtitle->extradata = NULL; - } - free( subtitle ); + hb_subtitle_close( &subtitle ); } hb_list_close( &t->list_subtitle ); while( ( attachment = hb_list_item( t->list_attachment, 0 ) ) ) { hb_list_rem( t->list_attachment, attachment ); - if ( attachment->name ) + hb_attachment_close( &attachment ); + } + hb_list_close( &t->list_attachment ); + + hb_metadata_close( &t->metadata ); + + free( t->video_codec_name ); + free(t->container_name); + +#if defined(HB_TITLE_JOBS) + hb_job_close( &t->job ); +#endif + + free( t ); + *_t = NULL; +} + +/* + * Create a pristine job structure from a title + * title_index is 1 based + */ +hb_job_t * hb_job_init_by_index( hb_handle_t * h, int title_index ) +{ + hb_title_set_t *title_set = hb_get_title_set( h ); + hb_title_t * title = hb_list_item( title_set->list_title, + title_index - 1 ); + return hb_job_init( title ); +} + +hb_job_t * hb_job_init( hb_title_t * title ) +{ + hb_job_t * job; + + if ( title == NULL ) + return NULL; + + job = calloc( sizeof( hb_job_t ), 1 ); + + job->title = title; + + /* Set defaults settings */ + job->chapter_start = 1; + job->chapter_end = hb_list_count( title->list_chapter ); + job->list_chapter = hb_chapter_list_copy( title->list_chapter ); + + /* Autocrop by default. Gnark gnark */ + memcpy( job->crop, title->crop, 4 * sizeof( int ) ); + + /* Preserve a source's pixel aspect, if it's available. */ + if( title->pixel_aspect_width && title->pixel_aspect_height ) + { + job->anamorphic.par_width = title->pixel_aspect_width; + job->anamorphic.par_height = title->pixel_aspect_height; + } + + if( title->aspect != 0 && title->aspect != 1. && + !job->anamorphic.par_width && !job->anamorphic.par_height) + { + hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height, + (int)(title->aspect * title->height + 0.5), title->width ); + } + + job->width = title->width - job->crop[2] - job->crop[3]; + hb_fix_aspect( job, HB_KEEP_WIDTH ); + if( job->height > title->height - job->crop[0] - job->crop[1] ) + { + job->height = title->height - job->crop[0] - job->crop[1]; + hb_fix_aspect( job, HB_KEEP_HEIGHT ); + } + + job->keep_ratio = 1; + + job->vcodec = HB_VCODEC_FFMPEG_MPEG4; + job->vquality = -1.0; + job->vbitrate = 1000; + job->pass = 0; + job->vrate = title->rate; + job->vrate_base = title->rate_base; + + job->mux = HB_MUX_MP4; + + job->list_audio = hb_list_init(); + job->list_subtitle = hb_list_init(); + job->list_filter = hb_list_init(); + + job->list_attachment = hb_attachment_list_copy( title->list_attachment ); + job->metadata = hb_metadata_copy( title->metadata ); + + return job; +} + +/** + * Clean up the job structure so that is is ready for setting up a new job. + * Should be called by front-ends after hb_add(). + */ +/********************************************************************** + * hb_job_reset + ********************************************************************** + * + *********************************************************************/ +void hb_job_reset( hb_job_t * job ) +{ + if ( job ) + { + hb_audio_t *audio; + hb_subtitle_t *subtitle; + hb_filter_object_t *filter; + hb_title_t * title = job->title; + + // clean up audio list + while( ( audio = hb_list_item( job->list_audio, 0 ) ) ) + { + hb_list_rem( job->list_audio, audio ); + hb_audio_close( &audio ); + } + + // clean up subtitle list + while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) ) { - free( attachment->name ); - attachment->name = NULL; + hb_list_rem( job->list_subtitle, subtitle ); + hb_subtitle_close( &subtitle ); } - if ( attachment->data ) + + // clean up filter list + while( ( filter = hb_list_item( job->list_filter, 0 ) ) ) { - free( attachment->data ); - attachment->data = NULL; + hb_list_rem( job->list_filter, filter ); + hb_filter_close( &filter ); } - free( attachment ); + + hb_metadata_close( &job->metadata ); + job->metadata = hb_metadata_copy( title->metadata ); } - hb_list_close( &t->list_attachment ); +} - if( t->metadata ) +/********************************************************************** + * hb_job_close + ********************************************************************** + * + *********************************************************************/ +void hb_job_close( hb_job_t ** _j ) +{ + if (_j) { - if( t->metadata->coverart ) + hb_job_t * job = *_j; + + if (job) { - free( t->metadata->coverart ); + hb_chapter_t *chapter; + hb_audio_t *audio; + hb_subtitle_t *subtitle; + hb_filter_object_t *filter; + hb_attachment_t *attachment; + + free(job->file); + free(job->advanced_opts); + + // clean up chapter list + while( ( chapter = hb_list_item( job->list_chapter, 0 ) ) ) + { + hb_list_rem( job->list_chapter, chapter ); + hb_chapter_close( &chapter ); + } + hb_list_close( &job->list_chapter ); + + // clean up audio list + while( ( audio = hb_list_item( job->list_audio, 0 ) ) ) + { + hb_list_rem( job->list_audio, audio ); + hb_audio_close( &audio ); + } + hb_list_close( &job->list_audio ); + + // clean up subtitle list + while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) ) + { + hb_list_rem( job->list_subtitle, subtitle ); + hb_subtitle_close( &subtitle ); + } + hb_list_close( &job->list_subtitle ); + + // clean up filter list + while( ( filter = hb_list_item( job->list_filter, 0 ) ) ) + { + hb_list_rem( job->list_filter, filter ); + hb_filter_close( &filter ); + } + hb_list_close( &job->list_filter ); + + // clean up attachment list + while( ( attachment = hb_list_item( job->list_attachment, 0 ) ) ) + { + hb_list_rem( job->list_attachment, attachment ); + hb_attachment_close( &attachment ); + } + hb_list_close( &job->list_attachment ); + + // clean up metadata + if ( job->metadata ) + { + hb_metadata_close( &job->metadata ); + } + free( job ); } - free( t->metadata ); + _j = NULL; } +} - if ( t->video_codec_name ) +void hb_job_set_file( hb_job_t *job, const char *file ) +{ + if ( job ) { - free( t->video_codec_name ); + hb_update_str( &job->file, file ); } +} - free( t ); - *_t = NULL; +void hb_job_set_advanced_opts( hb_job_t *job, const char *advanced_opts ) +{ + if ( job ) + { + hb_update_str( &job->advanced_opts, advanced_opts ); + } } hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter ) @@ -1689,6 +1890,30 @@ hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter ) return filter_copy; } +/********************************************************************** + * hb_filter_list_copy + ********************************************************************** + * + *********************************************************************/ +hb_list_t *hb_filter_list_copy(const hb_list_t *src) +{ + hb_list_t *list = hb_list_init(); + hb_filter_object_t *filter = NULL; + int i; + + if( src ) + { + for( i = 0; i < hb_list_count(src); i++ ) + { + if( ( filter = hb_list_item( src, i ) ) ) + { + hb_list_add( list, hb_filter_copy(filter) ); + } + } + } + return list; +} + /** * Gets a filter object with the given type * @param filter_id The type of filter to get. @@ -1759,6 +1984,93 @@ void hb_filter_close( hb_filter_object_t ** _f ) } /********************************************************************** + * hb_chapter_copy + ********************************************************************** + * + *********************************************************************/ +hb_chapter_t *hb_chapter_copy(const hb_chapter_t *src) +{ + hb_chapter_t *chap = NULL; + + if ( src ) + { + chap = calloc( 1, sizeof(*chap) ); + memcpy( chap, src, sizeof(*chap) ); + if ( src->title ) + { + chap->title = strdup( src->title ); + } + } + return chap; +} + +/********************************************************************** + * hb_chapter_list_copy + ********************************************************************** + * + *********************************************************************/ +hb_list_t *hb_chapter_list_copy(const hb_list_t *src) +{ + hb_list_t *list = hb_list_init(); + hb_chapter_t *chapter = NULL; + int i; + + if( src ) + { + for( i = 0; i < hb_list_count(src); i++ ) + { + if( ( chapter = hb_list_item( src, i ) ) ) + { + hb_list_add( list, hb_chapter_copy(chapter) ); + } + } + } + return list; +} + +/********************************************************************** + * hb_chapter_close + ********************************************************************** + * + *********************************************************************/ +void hb_chapter_close(hb_chapter_t **chap) +{ + if ( chap && *chap ) + { + free((*chap)->title); + free(*chap); + *chap = NULL; + } +} + +/********************************************************************** + * hb_chapter_set_title + ********************************************************************** + * + *********************************************************************/ +void hb_chapter_set_title( hb_chapter_t *chapter, const char *title ) +{ + if ( chapter ) + { + hb_update_str( &chapter->title, title ); + } +} + +/********************************************************************** + * hb_chapter_set_title_by_index + ********************************************************************** + * Applies information from the given job to the official job instance. + * @param job Handle to hb_job_t. + * @param chapter The chapter to apply the name to (1-based). + * @param titel to apply. + *********************************************************************/ +void hb_chapter_set_title_by_index( hb_job_t * job, int chapter_index, const char * title ) +{ + hb_chapter_t * chapter = hb_list_item( job->list_chapter, chapter_index - 1 ); + hb_chapter_set_title( chapter, title ); +} + +/********************************************************************** * hb_audio_copy ********************************************************************** * @@ -1771,11 +2083,54 @@ hb_audio_t *hb_audio_copy(const hb_audio_t *src) { audio = calloc(1, sizeof(*audio)); memcpy(audio, src, sizeof(*audio)); + if ( src->config.out.name ) + { + audio->config.out.name = strdup(src->config.out.name); + } } return audio; } /********************************************************************** + * hb_audio_list_copy + ********************************************************************** + * + *********************************************************************/ +hb_list_t *hb_audio_list_copy(const hb_list_t *src) +{ + hb_list_t *list = hb_list_init(); + hb_audio_t *audio = NULL; + int i; + + if( src ) + { + for( i = 0; i < hb_list_count(src); i++ ) + { + if( ( audio = hb_list_item( src, i ) ) ) + { + hb_list_add( list, hb_audio_copy(audio) ); + } + } + } + return list; +} + +/********************************************************************** + * hb_audio_close + ********************************************************************** + * + *********************************************************************/ +void hb_audio_close( hb_audio_t **audio ) +{ + if ( audio && *audio ) + { + free((*audio)->config.out.name); + free(*audio); + *audio = NULL; + } +} + +/********************************************************************** * hb_audio_new ********************************************************************** * @@ -1878,7 +2233,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) } if (audiocfg->out.name && *audiocfg->out.name) { - audio->config.out.name = audiocfg->out.name; + audio->config.out.name = strdup(audiocfg->out.name); } hb_list_add(job->list_audio, audio); @@ -1918,6 +2273,45 @@ hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src) } /********************************************************************** + * hb_subtitle_list_copy + ********************************************************************** + * + *********************************************************************/ +hb_list_t *hb_subtitle_list_copy(const hb_list_t *src) +{ + hb_list_t *list = hb_list_init(); + hb_subtitle_t *subtitle = NULL; + int i; + + if( src ) + { + for( i = 0; i < hb_list_count(src); i++ ) + { + if( ( subtitle = hb_list_item( src, i ) ) ) + { + hb_list_add( list, hb_subtitle_copy(subtitle) ); + } + } + } + return list; +} + +/********************************************************************** + * hb_subtitle_close + ********************************************************************** + * + *********************************************************************/ +void hb_subtitle_close( hb_subtitle_t **sub ) +{ + if ( sub && *sub ) + { + free ((*sub)->extradata); + free(*sub); + *sub = NULL; + } +} + +/********************************************************************** * hb_subtitle_add ********************************************************************** * @@ -2026,6 +2420,238 @@ int hb_subtitle_can_pass( int source, int mux ) } } +/********************************************************************** + * hb_metadata_init + ********************************************************************** + * + *********************************************************************/ +hb_metadata_t *hb_metadata_init() +{ + hb_metadata_t *metadata = calloc( 1, sizeof(*metadata) ); + return metadata; +} + +/********************************************************************** + * hb_metadata_copy + ********************************************************************** + * + *********************************************************************/ +hb_metadata_t *hb_metadata_copy( const hb_metadata_t *src ) +{ + hb_metadata_t *metadata = NULL; + + if ( src ) + { + metadata = calloc( 1, sizeof(*metadata) ); + if ( src->name ) + { + metadata->name = strdup(src->name); + } + if ( src->artist ) + { + metadata->artist = strdup(src->artist); + } + if ( src->album_artist ) + { + metadata->album_artist = strdup(src->album_artist); + } + if ( src->composer ) + { + metadata->composer = strdup(src->composer); + } + if ( src->release_date ) + { + metadata->release_date = strdup(src->release_date); + } + if ( src->comment ) + { + metadata->comment = strdup(src->comment); + } + if ( src->album ) + { + metadata->album = strdup(src->album); + } + if ( src->genre ) + { + metadata->genre = strdup(src->genre); + } + if ( src->description ) + { + metadata->description = strdup(src->description); + } + if ( src->long_description ) + { + metadata->long_description = strdup(src->long_description); + } + if ( src->list_coverart ) + { + int ii; + for ( ii = 0; ii < hb_list_count( src->list_coverart ); ii++ ) + { + hb_coverart_t *art = hb_list_item( src->list_coverart, ii ); + hb_metadata_add_coverart( + metadata, art->data, art->size, art->type ); + } + } + } + return metadata; +} + +/********************************************************************** + * hb_metadata_close + ********************************************************************** + * + *********************************************************************/ +void hb_metadata_close( hb_metadata_t **_m ) +{ + if ( _m && *_m ) + { + hb_metadata_t *m = *_m; + hb_coverart_t *art; + + free( m->name ); + free( m->artist ); + free( m->composer ); + free( m->release_date ); + free( m->comment ); + free( m->album ); + free( m->album_artist ); + free( m->genre ); + free( m->description ); + free( m->long_description ); + + if ( m->list_coverart ) + { + while( ( art = hb_list_item( m->list_coverart, 0 ) ) ) + { + hb_list_rem( m->list_coverart, art ); + free( art->data ); + free( art ); + } + hb_list_close( &m->list_coverart ); + } + + free( m ); + *_m = NULL; + } +} + +/********************************************************************** + * hb_metadata_set_* + ********************************************************************** + * + *********************************************************************/ +void hb_metadata_set_name( hb_metadata_t *metadata, const char *name ) +{ + if ( metadata ) + { + hb_update_str( &metadata->name, name ); + } +} + +void hb_metadata_set_artist( hb_metadata_t *metadata, const char *artist ) +{ + if ( metadata ) + { + hb_update_str( &metadata->artist, artist ); + } +} + +void hb_metadata_set_composer( hb_metadata_t *metadata, const char *composer ) +{ + if ( metadata ) + { + hb_update_str( &metadata->composer, composer ); + } +} + +void hb_metadata_set_release_date( hb_metadata_t *metadata, const char *release_date ) +{ + if ( metadata ) + { + hb_update_str( &metadata->release_date, release_date ); + } +} + +void hb_metadata_set_comment( hb_metadata_t *metadata, const char *comment ) +{ + if ( metadata ) + { + hb_update_str( &metadata->comment, comment ); + } +} + +void hb_metadata_set_genre( hb_metadata_t *metadata, const char *genre ) +{ + if ( metadata ) + { + hb_update_str( &metadata->genre, genre ); + } +} + +void hb_metadata_set_album( hb_metadata_t *metadata, const char *album ) +{ + if ( metadata ) + { + hb_update_str( &metadata->album, album ); + } +} + +void hb_metadata_set_album_artist( hb_metadata_t *metadata, const char *album_artist ) +{ + if ( metadata ) + { + hb_update_str( &metadata->album_artist, album_artist ); + } +} + +void hb_metadata_set_description( hb_metadata_t *metadata, const char *description ) +{ + if ( metadata ) + { + hb_update_str( &metadata->description, description ); + } +} + +void hb_metadata_set_long_description( hb_metadata_t *metadata, const char *long_description ) +{ + if ( metadata ) + { + hb_update_str( &metadata->long_description, long_description ); + } +} + +void hb_metadata_add_coverart( hb_metadata_t *metadata, const uint8_t *data, int size, int type ) +{ + if ( metadata ) + { + if ( metadata->list_coverart == NULL ) + { + metadata->list_coverart = hb_list_init(); + } + hb_coverart_t *art = calloc( 1, sizeof(hb_coverart_t) ); + art->data = malloc( size ); + memcpy( art->data, data, size ); + art->size = size; + art->type = type; + hb_list_add( metadata->list_coverart, art ); + } +} + +void hb_metadata_rem_coverart( hb_metadata_t *metadata, int idx ) +{ + if ( metadata ) + { + hb_coverart_t *art = hb_list_item( metadata->list_coverart, idx ); + if ( art ) + { + hb_list_rem( metadata->list_coverart, art ); + free( art->data ); + free( art ); + } + } +} + char * hb_strdup_printf( const char * fmt, ... ) { int len; @@ -2119,6 +2745,46 @@ hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src) } /********************************************************************** + * hb_attachment_list_copy + ********************************************************************** + * + *********************************************************************/ +hb_list_t *hb_attachment_list_copy(const hb_list_t *src) +{ + hb_list_t *list = hb_list_init(); + hb_attachment_t *attachment = NULL; + int i; + + if( src ) + { + for( i = 0; i < hb_list_count(src); i++ ) + { + if( ( attachment = hb_list_item( src, i ) ) ) + { + hb_list_add( list, hb_attachment_copy(attachment) ); + } + } + } + return list; +} + +/********************************************************************** + * hb_attachment_close + ********************************************************************** + * + *********************************************************************/ +void hb_attachment_close( hb_attachment_t **attachment ) +{ + if ( attachment && *attachment ) + { + free((*attachment)->data); + free((*attachment)->name); + free(*attachment); + *attachment = NULL; + } +} + +/********************************************************************** * hb_yuv2rgb ********************************************************************** * Converts a YCrCb pixel to an RGB pixel. diff --git a/libhb/common.h b/libhb/common.h index f7cc6dfef..41711e954 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -73,6 +73,7 @@ typedef struct hb_rate_s hb_rate_t; typedef struct hb_mixdown_s hb_mixdown_t; typedef struct hb_encoder_s hb_encoder_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; typedef struct hb_chapter_s hb_chapter_t; typedef struct hb_audio_s hb_audio_t; @@ -81,6 +82,7 @@ typedef struct hb_subtitle_s hb_subtitle_t; typedef struct hb_subtitle_config_s hb_subtitle_config_t; typedef struct hb_attachment_s hb_attachment_t; typedef struct hb_metadata_s hb_metadata_t; +typedef struct hb_coverart_s hb_coverart_t; typedef struct hb_state_s hb_state_t; typedef union hb_esconfig_u hb_esconfig_t; typedef struct hb_work_private_s hb_work_private_t; @@ -102,11 +104,11 @@ typedef struct hb_lock_s hb_lock_t; #include "libavutil/audioconvert.h" hb_list_t * hb_list_init(); -int hb_list_count( hb_list_t * ); +int hb_list_count( const hb_list_t * ); void hb_list_add( hb_list_t *, void * ); void hb_list_insert( hb_list_t * l, int pos, void * p ); void hb_list_rem( hb_list_t *, void * ); -void * hb_list_item( hb_list_t *, int ); +void * hb_list_item( const hb_list_t *, int ); void hb_list_close( hb_list_t ** ); void hb_reduce( int *x, int *y, int num, int den ); @@ -117,12 +119,19 @@ void hb_limit_rational64( int64_t *x, int64_t *y, int64_t num, int64_t den, int6 #define HB_KEEP_HEIGHT 1 void hb_fix_aspect( hb_job_t * job, int keep ); +void hb_job_set_advanced_opts( hb_job_t *job, const char *advanced_opts ); +void hb_job_set_file( hb_job_t *job, const char *file ); + hb_audio_t *hb_audio_copy(const hb_audio_t *src); +hb_list_t *hb_audio_list_copy(const hb_list_t *src); +void hb_audio_close(hb_audio_t **audio); void hb_audio_config_init(hb_audio_config_t * audiocfg); int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg); hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i); hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src); +hb_list_t *hb_subtitle_list_copy(const hb_list_t *src); +void hb_subtitle_close( hb_subtitle_t **sub ); int hb_subtitle_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, int track); int hb_srt_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, const char *lang); @@ -131,6 +140,29 @@ int hb_subtitle_can_burn( int source ); int hb_subtitle_can_pass( int source, int mux ); hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src); +hb_list_t *hb_attachment_list_copy(const hb_list_t *src); +void hb_attachment_close(hb_attachment_t **attachment); + +hb_metadata_t * hb_metadata_init(); +hb_metadata_t * hb_metadata_copy(const hb_metadata_t *src); +void hb_metadata_close(hb_metadata_t **metadata); +void hb_metadata_set_name( hb_metadata_t *metadata, const char *name ); +void hb_metadata_set_artist( hb_metadata_t *metadata, const char *artist ); +void hb_metadata_set_composer( hb_metadata_t *metadata, const char *composer ); +void hb_metadata_set_release_date( hb_metadata_t *metadata, const char *release_date ); +void hb_metadata_set_comment( hb_metadata_t *metadata, const char *comment ); +void hb_metadata_set_genre( hb_metadata_t *metadata, const char *genre ); +void hb_metadata_set_album( hb_metadata_t *metadata, const char *album ); +void hb_metadata_set_album_artist( hb_metadata_t *metadata, const char *album_artist ); +void hb_metadata_set_description( hb_metadata_t *metadata, const char *description ); +void hb_metadata_set_long_description( hb_metadata_t *metadata, const char *long_description ); +void hb_metadata_add_coverart( hb_metadata_t *metadata, const uint8_t *data, int size, int type ); +void hb_metadata_rem_coverart( hb_metadata_t *metadata, int ii ); + +hb_chapter_t *hb_chapter_copy(const hb_chapter_t *src); +hb_list_t *hb_chapter_list_copy(const hb_list_t *src); +void hb_chapter_close(hb_chapter_t **chapter); +void hb_chapter_set_title(hb_chapter_t *chapter, const char *title); struct hb_rate_s { @@ -205,7 +237,9 @@ int hb_mixdown_get_low_freq_channel_count(int amixdown); int hb_mixdown_get_mixdown_from_short_name(const char *short_name); const char* hb_mixdown_get_short_name_from_mixdown(int amixdown); -void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title ); +int hb_mixdown_get_mixdown_from_short_name( const char * short_name ); +const char * hb_mixdown_get_short_name_from_mixdown( int amixdown ); +void hb_autopassthru_apply_settings( hb_job_t * job ); void hb_autopassthru_print_settings( hb_job_t * job ); int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer ); int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown); @@ -222,6 +256,12 @@ void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, fl float hb_get_best_audio_compression( uint32_t codec, float compression); float hb_get_default_audio_compression( uint32_t codec ); +struct hb_title_set_s +{ + hb_list_t * list_title; + int feature; // Detected DVD feature title +}; + /****************************************************************************** * hb_job_t: settings to be filled by the UI *****************************************************************************/ @@ -333,6 +373,8 @@ struct hb_job_s #define HB_COLR_MAT_SMPTE240M 7 // 0, 3-5, 8-65535: reserved + hb_list_t * list_chapter; + /* List of audio settings. */ hb_list_t * list_audio; int acodec_copy_mask; // Auto Passthru allowed codecs @@ -341,6 +383,10 @@ struct hb_job_s /* Subtitles */ hb_list_t * list_subtitle; + hb_list_t * list_attachment; + + hb_metadata_t * metadata; + /* Muxer settings mux: output file format file: file path */ @@ -349,7 +395,7 @@ struct hb_job_s #define HB_MUX_MKV 0x200000 int mux; - const char * file; + char * file; /* Allow MP4 files > 4 gigs */ int largeFileSize; @@ -534,7 +580,7 @@ struct hb_chapter_s uint64_t duration; /* Optional chapter title */ - char title[1024]; + char *title; }; /* @@ -615,23 +661,38 @@ struct hb_subtitle_s */ struct hb_attachment_s { - enum attachtype { FONT_TTF_ATTACH } type; + enum attachtype { FONT_TTF_ATTACH, HB_ART_ATTACH } type; char * name; char * data; int size; }; +struct hb_coverart_s +{ + uint8_t *data; + uint32_t size; + enum arttype { + HB_ART_UNDEFINED, + HB_ART_BMP, + HB_ART_GIF, + HB_ART_PNG, + HB_ART_JPEG + } type; +}; + struct hb_metadata_s { - char name[255]; - char artist[255]; - char composer[255]; - char release_date[255]; - char comment[1024]; - char album[255]; - char genre[255]; - uint32_t coverart_size; - uint8_t *coverart; + char *name; + char *artist; // Actors + char *composer; + char *release_date; + char *comment; + char *album; // DVD + char *album_artist; // Director + char *genre; + char *description; + char *long_description; + hb_list_t * list_coverart; }; struct hb_title_s @@ -682,7 +743,7 @@ struct hb_title_s int video_codec_param; /* codec specific config */ char *video_codec_name; int video_bitrate; - const char *container_name; + char *container_name; int data_rate; hb_metadata_t *metadata; @@ -692,12 +753,15 @@ struct hb_title_s hb_list_t * list_subtitle; hb_list_t * list_attachment; - /* Job template for this title */ +#define HB_TITLE_JOBS +#if defined(HB_TITLE_JOBS) hb_job_t * job; +#endif uint32_t flags; // set if video stream doesn't have IDR frames #define HBTF_NO_IDR (1 << 0) +#define HBTF_SCAN_COMPLETE (1 << 0) }; @@ -941,7 +1005,8 @@ enum hb_filter_object_t * hb_filter_init( int filter_id ); hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter ); -void hb_filter_close( hb_filter_object_t ** ); +hb_list_t *hb_filter_list_copy(const hb_list_t *src); +void hb_filter_close( hb_filter_object_t ** ); typedef void hb_error_handler_t( const char *errmsg ); diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 4fd22c833..dd3c8879d 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -565,7 +565,7 @@ static void log_chapter( hb_work_private_t *pv, int chap_num, int64_t pts ) if ( !pv->job ) return; - c = hb_list_item( pv->job->title->list_chapter, chap_num - 1 ); + c = hb_list_item( pv->job->list_chapter, chap_num - 1 ); if ( c && c->title ) { hb_log( "%s: \"%s\" (%d) at frame %u time %"PRId64, diff --git a/libhb/decmetadata.c b/libhb/decmetadata.c index e3829de09..513e64fbe 100644 --- a/libhb/decmetadata.c +++ b/libhb/decmetadata.c @@ -11,9 +11,10 @@ #include "common.h" -static void decmp4metadata( hb_title_t *title ) +static int decmp4metadata( hb_title_t *title ) { MP4FileHandle input_file; + int result = 0; hb_deep_log( 2, "Got an MP4 input, read the metadata"); input_file = MP4Read( title->path, 0 ); @@ -31,35 +32,93 @@ static void decmp4metadata( hb_title_t *title ) if( tags->name ) { hb_deep_log( 2, "Metadata Name in input file is '%s'", tags->name ); - strncpy( title->metadata->name, tags->name, sizeof(title->metadata->name) ); + hb_metadata_set_name(title->metadata, tags->name); + result = 1; } if( tags->artist ) - strncpy( title->metadata->artist, tags->artist, sizeof(title->metadata->artist) ); + { + hb_metadata_set_artist(title->metadata, tags->artist); + result = 1; + } if( tags->composer ) - strncpy( title->metadata->composer, tags->composer, sizeof(title->metadata->composer) ); + { + hb_metadata_set_composer(title->metadata, tags->composer); + result = 1; + } if( tags->comments ) - strncpy( title->metadata->comment, tags->comments, sizeof(title->metadata->comment) ); + { + hb_metadata_set_comment(title->metadata, tags->comments); + result = 1; + } if( tags->releaseDate ) - strncpy( title->metadata->release_date, tags->releaseDate, sizeof(title->metadata->release_date) ); + { + hb_metadata_set_release_date(title->metadata, tags->releaseDate); + result = 1; + } if( tags->album ) - strncpy( title->metadata->album, tags->album, sizeof(title->metadata->album) ); + { + hb_metadata_set_album(title->metadata, tags->album); + result = 1; + } + + if( tags->albumArtist ) + { + hb_metadata_set_album_artist(title->metadata, tags->albumArtist); + result = 1; + } if( tags->genre ) - strncpy( title->metadata->genre, tags->genre, sizeof(title->metadata->genre) ); + { + hb_metadata_set_genre(title->metadata, tags->genre); + result = 1; + } + + if( tags->description ) + { + hb_metadata_set_description(title->metadata, tags->description); + result = 1; + } + + if( tags->longDescription ) + { + hb_metadata_set_long_description(title->metadata, tags->longDescription); + result = 1; + } - if( tags->artworkCount > 0 ) { - const MP4TagArtwork* art = tags->artwork + 0; // first element - title->metadata->coverart = (uint8_t*)malloc( art->size ); - title->metadata->coverart_size = art->size; - memcpy( title->metadata->coverart, art->data, art->size ); + int ii; + for ( ii = 0; ii < tags->artworkCount; ii++ ) + { + const MP4TagArtwork* art = tags->artwork + ii; + int type; + switch ( art->type ) + { + case MP4_ART_BMP: + type = HB_ART_BMP; + break; + case MP4_ART_GIF: + type = HB_ART_GIF; + break; + case MP4_ART_JPEG: + type = HB_ART_JPEG; + break; + case MP4_ART_PNG: + type = HB_ART_PNG; + break; + default: + type = HB_ART_UNDEFINED; + break; + } + hb_metadata_add_coverart( + title->metadata, art->data, art->size, type); hb_deep_log( 2, "Got some cover art of type %d, size %d", art->type, - title->metadata->coverart_size ); + art->size ); + result = 1; } /* store,free tags */ @@ -91,11 +150,13 @@ static void decmp4metadata( hb_title_t *title ) if( chapter_list[i-1].title ) { - strcpy( chapter->title, chapter_list[i-1].title ); + hb_chapter_set_title( chapter, chapter_list[i-1].title ); } else { - sprintf( chapter->title, "Chapter %d", chapter->index ); + char chapter_title[80]; + sprintf( chapter_title, "Chapter %d", chapter->index ); + hb_chapter_set_title( chapter, chapter_title ); } hb_deep_log( 2, "Added chapter %i, name='%s', dur=%"PRId64", (%02i:%02i:%02i)", @@ -109,6 +170,7 @@ static void decmp4metadata( hb_title_t *title ) MP4Close( input_file ); } + return result; } /* @@ -116,24 +178,16 @@ static void decmp4metadata( hb_title_t *title ) * * Look at the title and extract whatever metadata we can from that title. */ -void decmetadata( hb_title_t *title ) +int decmetadata( hb_title_t *title ) { if( !title ) { - return; + return 0; } - if( title->metadata ) - { - free( title->metadata ); - title->metadata = NULL; - } - - title->metadata = calloc( sizeof(hb_metadata_t), 1); - if( !title->metadata ) { - return; + return 0; } /* @@ -141,9 +195,7 @@ void decmetadata( hb_title_t *title ) */ if( title->container_name && strcmp(title->container_name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 ) { - decmp4metadata( title ); - } else { - free( title->metadata ); - title->metadata = NULL; + return decmp4metadata( title ); } + return 0; } diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c index 311fc93c8..991feb8e9 100644 --- a/libhb/decmpeg2.c +++ b/libhb/decmpeg2.c @@ -498,11 +498,11 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, m->look_for_iframe = 0; const char *chap_name = ""; if ( m->job && new_chap > 0 && - hb_list_item( m->job->title->list_chapter, + hb_list_item( m->job->list_chapter, new_chap - 1 ) ) { hb_chapter_t * c = hb_list_item( - m->job->title->list_chapter, + m->job->list_chapter, new_chap - 1 ); chap_name = c->title; } @@ -514,10 +514,10 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es, { // this is the first frame returned by the decoder m->first_pts = buf->s.start; - if ( m->job && hb_list_item( m->job->title->list_chapter, + if ( m->job && hb_list_item( m->job->list_chapter, m->job->chapter_start - 1 ) ) { - hb_chapter_t * c = hb_list_item( m->job->title->list_chapter, + hb_chapter_t * c = hb_list_item( m->job->list_chapter, m->job->chapter_start - 1 ); hb_log( "mpeg2: \"%s\" (%d) at frame %u time %"PRId64, c->title, m->job->chapter_start, m->nframes, buf->s.start ); diff --git a/libhb/decsrtsub.c b/libhb/decsrtsub.c index 55004c05f..6d1754068 100644 --- a/libhb/decsrtsub.c +++ b/libhb/decsrtsub.c @@ -464,7 +464,6 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) hb_buffer_t *buffer; int i; hb_chapter_t * chapter; - hb_title_t *title = job->title; pv = calloc( 1, sizeof( hb_work_private_t ) ); if( pv ) @@ -489,7 +488,7 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) pv->start_time = 0; for( i = 1; i < job->chapter_start; ++i ) { - chapter = hb_list_item( title->list_chapter, i - 1 ); + chapter = hb_list_item( job->list_chapter, i - 1 ); if( chapter ) { pv->start_time += chapter->duration; @@ -501,7 +500,7 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) pv->stop_time = pv->start_time; for( i = job->chapter_start; i <= job->chapter_end; ++i ) { - chapter = hb_list_item( title->list_chapter, i - 1 ); + chapter = hb_list_item( job->list_chapter, i - 1 ); if( chapter ) { pv->stop_time += chapter->duration; diff --git a/libhb/dvd.c b/libhb/dvd.c index 1a273f977..f342b5474 100644 --- a/libhb/dvd.c +++ b/libhb/dvd.c @@ -561,11 +561,13 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur for( i = 0; i < vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ ) { + char chapter_title[80]; chapter = calloc( sizeof( hb_chapter_t ), 1 ); /* remember the on-disc chapter number */ chapter->index = i + 1; - sprintf( chapter->title, "Chapter %d", chapter->index ); + sprintf( chapter_title, "Chapter %d", chapter->index ); + hb_chapter_set_title( chapter, chapter_title ); pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgcn; pgn = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgn; diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c index 638b6e5af..c1f152efd 100644 --- a/libhb/dvdnav.c +++ b/libhb/dvdnav.c @@ -740,12 +740,14 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura for (i = pgn; i <= pgc->nr_of_programs; i++) { + char chapter_title[80]; chapter = calloc( sizeof( hb_chapter_t ), 1 ); chapter->pgcn = pgcn; chapter->pgn = i; chapter->index = c + 1; - sprintf( chapter->title, "Chapter %d", chapter->index ); + sprintf( chapter_title, "Chapter %d", chapter->index ); + hb_chapter_set_title( chapter, chapter_title ); hb_list_add( title->list_chapter, chapter ); c++; diff --git a/libhb/hb.c b/libhb/hb.c index 52ddc206b..8a1ec3b1e 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -36,7 +36,7 @@ struct hb_handle_s int pid; /* DVD/file scan thread */ - hb_list_t * list_title; + hb_title_set_t title_set; hb_thread_t * scan_thread; /* The thread which processes the jobs. Others threads are launched @@ -71,7 +71,6 @@ int hb_instance_counter = 0; int hb_process_initialized = 0; static void thread_func( void * ); -hb_title_t * hb_get_title_by_index( hb_handle_t *, int ); static int ff_lockmgr_cb(void **mutex, enum AVLockOp op) { @@ -432,7 +431,7 @@ hb_handle_t * hb_init( int verbose, int update_check ) */ hb_buffer_pool_init(); - h->list_title = hb_list_init(); + h->title_set.list_title = hb_list_init(); h->jobs = hb_list_init(); h->state_lock = hb_lock_init(); @@ -531,7 +530,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) } } - h->list_title = hb_list_init(); + h->title_set.list_title = hb_list_init(); h->jobs = hb_list_init(); h->current_job = NULL; @@ -631,7 +630,7 @@ void hb_remove_previews( hb_handle_t * h ) dir = opendir( dirname ); if (dir == NULL) return; - count = hb_list_count( h->list_title ); + count = hb_list_count( h->title_set.list_title ); while( ( entry = readdir( dir ) ) ) { if( entry->d_name[0] == '.' ) @@ -640,7 +639,7 @@ void hb_remove_previews( hb_handle_t * h ) } for( i = 0; i < count; i++ ) { - title = hb_list_item( h->list_title, i ); + title = hb_list_item( h->title_set.list_title, i ); len = snprintf( filename, 1024, "%d_%d", h->id, title->index ); if (strncmp(entry->d_name, filename, len) == 0) { @@ -670,15 +669,15 @@ void hb_scan( hb_handle_t * h, const char * path, int title_index, /* Clean up from previous scan */ hb_remove_previews( h ); - while( ( title = hb_list_item( h->list_title, 0 ) ) ) + while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) ) { - hb_list_rem( h->list_title, title ); + hb_list_rem( h->title_set.list_title, title ); hb_title_close( &title ); } hb_log( "hb_scan: path=%s, title_index=%d", path, title_index ); h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index, - h->list_title, preview_count, + &h->title_set, preview_count, store_previews, min_duration ); } @@ -689,25 +688,12 @@ void hb_scan( hb_handle_t * h, const char * path, int title_index, */ hb_list_t * hb_get_titles( hb_handle_t * h ) { - return h->list_title; + return h->title_set.list_title; } -/** - * Create preview image of desired title a index of picture. - * @param h Handle to hb_handle_t. - * @param title_index Index of the title to get the preview for (1-based). - * @param picture Index in title. - * @param buffer Handle to buffer were image will be drawn. - */ -void hb_get_preview_by_index( hb_handle_t * h, int title_index, int picture, uint8_t * buffer ) +hb_title_set_t * hb_get_title_set( hb_handle_t * h ) { - hb_title_t * title; - - title = hb_get_title_by_index( h, title_index ); - if ( title != NULL ) - { - hb_get_preview( h, title, picture, buffer ); - } + return &h->title_set; } int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf ) @@ -747,12 +733,16 @@ hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, 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(h->list_title); ii++) + for (ii = 0; ii < hb_list_count(title_set->list_title); ii++) { - title = hb_list_item( h->list_title, ii); + title = hb_list_item( title_set->list_title, ii); if (title != NULL && title->index == title_idx) { break; @@ -804,10 +794,10 @@ hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ) * @param picture Index in title. * @param buffer Handle to buffer were image will be drawn. */ -void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, +void hb_get_preview( hb_handle_t * h, hb_job_t * job, int picture, uint8_t * buffer ) { - hb_job_t * job = title->job; + hb_title_t * title = job->title; char filename[1024]; hb_buffer_t * in_buf, * deint_buf = NULL, * preview_buf; uint8_t * pen; @@ -991,26 +981,6 @@ int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int thre /** * Calculates job width and height for anamorphic content, * - * @param h Instance handle - * @param title_index Index of the title/job to inspect (1-based). - * @param output_width Pointer to returned storage width - * @param output_height Pointer to returned storage height - * @param output_par_width Pointer to returned pixel width - * @param output_par_height Pointer to returned pixel height - */ -void hb_set_anamorphic_size_by_index( hb_handle_t * h, int title_index, - int *output_width, int *output_height, - int *output_par_width, int *output_par_height ) -{ - hb_title_t * title; - title = hb_get_title_by_index( h, title_index ); - - hb_set_anamorphic_size( title->job, output_width, output_height, output_par_width, output_par_height ); -} - -/** - * Calculates job width and height for anamorphic content, - * * @param job Handle to hb_job_t * @param output_width Pointer to returned storage width * @param output_height Pointer to returned storage height @@ -1423,53 +1393,6 @@ hb_job_t * hb_current_job( hb_handle_t * h ) } /** - * Applies information from the given job to the official job instance. - * @param h Handle to hb_handle_t. - * @param title_index Index of the title to apply the chapter name to (1-based). - * @param chapter The chapter to apply the name to (1-based). - * @param job Job information to apply. - */ -void hb_set_chapter_name( hb_handle_t * h, int title_index, int chapter_index, const char * chapter_name ) -{ - hb_title_t * title; - title = hb_get_title_by_index( h, title_index ); - - hb_chapter_t * chapter = hb_list_item( title->list_chapter, chapter_index - 1 ); - - strncpy(chapter->title, chapter_name, 1023); - chapter->title[1023] = '\0'; -} - -/** - * Applies information from the given job to the official job instance. - * Currently only applies information needed for anamorphic size calculation and previews. - * @param h Handle to hb_handle_t. - * @param title_index Index of the title to apply the job information to (1-based). - * @param job Job information to apply. - */ -void hb_set_job( hb_handle_t * h, int title_index, hb_job_t * job ) -{ - int i; - - hb_title_t * title; - title = hb_get_title_by_index( h, title_index ); - - hb_job_t * job_target = title->job; - - job_target->deinterlace = job->deinterlace; - job_target->width = job->width; - job_target->height = job->height; - job_target->maxWidth = job->maxWidth; - job_target->maxHeight = job->maxHeight; - for (i = 0; i < 4; i++) - { - job_target->crop[i] = job->crop[i]; - } - - job_target->anamorphic = job->anamorphic; -} - -/** * Adds a job to the job list. * @param h Handle to hb_handle_t. * @param job Handle to hb_job_t. @@ -1477,85 +1400,21 @@ void hb_set_job( hb_handle_t * h, int title_index, hb_job_t * job ) void hb_add( hb_handle_t * h, hb_job_t * job ) { hb_job_t * job_copy; - hb_title_t * title, * title_copy; - hb_chapter_t * chapter, * chapter_copy; hb_audio_t * audio; hb_subtitle_t * subtitle; - hb_attachment_t * attachment; int i; char audio_lang[4]; - /* Copy the title */ - title = job->title; - title_copy = malloc( sizeof( hb_title_t ) ); - memcpy( title_copy, title, sizeof( hb_title_t ) ); - - title_copy->list_chapter = hb_list_init(); - for( i = 0; i < hb_list_count( title->list_chapter ); i++ ) - { - chapter = hb_list_item( title->list_chapter, i ); - chapter_copy = malloc( sizeof( hb_chapter_t ) ); - memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) ); - hb_list_add( title_copy->list_chapter, chapter_copy ); - } - - /* - * Copy the metadata - */ - if( title->metadata ) - { - title_copy->metadata = malloc( sizeof( hb_metadata_t ) ); - - if( title_copy->metadata ) - { - memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) ); - - /* - * Need to copy the artwork seperatly (TODO). - */ - if( title->metadata->coverart ) - { - title_copy->metadata->coverart = malloc( title->metadata->coverart_size ); - if( title_copy->metadata->coverart ) - { - memcpy( title_copy->metadata->coverart, title->metadata->coverart, - title->metadata->coverart_size ); - } else { - title_copy->metadata->coverart_size = 0; - } - } - } - } - - /* Copy the audio track(s) we want */ - title_copy->list_audio = hb_list_init(); - for( i = 0; i < hb_list_count(job->list_audio); i++ ) - { - if( ( audio = hb_list_item( job->list_audio, i ) ) ) - { - hb_list_add( title_copy->list_audio, hb_audio_copy(audio) ); - } - } - - /* Initialize subtitle list - filled out further below */ - title_copy->list_subtitle = hb_list_init(); - - /* Copy all the attachments */ - title_copy->list_attachment = hb_list_init(); - for( i = 0; i < hb_list_count(title->list_attachment); i++ ) - { - if( ( attachment = hb_list_item( title->list_attachment, i ) ) ) - { - hb_list_add( title_copy->list_attachment, hb_attachment_copy(attachment) ); - } - } - title_copy->video_codec_name = strdup( title->video_codec_name ); + /* Copy the job */ + job_copy = calloc( sizeof( hb_job_t ), 1 ); + memcpy( job_copy, job, sizeof( hb_job_t ) ); - /* If we're doing Foreign Audio Search, copy all subtitles matching the first - * audio track language we find in the audio list. + /* If we're doing Foreign Audio Search, copy all subtitles matching the + * first audio track language we find in the audio list. * - * Otherwise, copy all subtitles found in the input job (which can be manually - * selected by the user, or added after the Foreign Audio Search pass). */ + * Otherwise, copy all subtitles found in the input job (which can be + * manually selected by the user, or added after the Foreign Audio + * Search pass). */ memset( audio_lang, 0, sizeof( audio_lang ) ); if( job->indepth_scan ) @@ -1571,9 +1430,16 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) break; } } - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + + /* + * If doing a subtitle scan then add all the matching subtitles for this + * language. + */ + job_copy->list_subtitle = hb_list_init(); + + for( i = 0; i < hb_list_count( job->title->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->title->list_subtitle, i ); if( strcmp( subtitle->iso639_2, audio_lang ) == 0 && hb_subtitle_can_force( subtitle->source ) ) { @@ -1582,54 +1448,31 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) * * We will update the subtitle list on the next pass later, after * the subtitle scan pass has completed. */ - hb_list_add( title_copy->list_subtitle, hb_subtitle_copy( subtitle ) ); + hb_list_add( job_copy->list_subtitle, + hb_subtitle_copy( subtitle ) ); } } } else { /* Copy all subtitles from the input job to title_copy/job_copy. */ - for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) - { - if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) ) - { - hb_list_add( title_copy->list_subtitle, hb_subtitle_copy( subtitle ) ); - } - } + job_copy->list_subtitle = hb_subtitle_list_copy( job->list_subtitle ); } - /* Copy the job */ - job_copy = calloc( sizeof( hb_job_t ), 1 ); - memcpy( job_copy, job, sizeof( hb_job_t ) ); - title_copy->job = job_copy; - job_copy->title = title_copy; - job_copy->list_audio = title_copy->list_audio; - job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job - job_copy->file = strdup( job->file ); + job_copy->list_chapter = hb_chapter_list_copy( job->list_chapter ); + job_copy->list_audio = hb_audio_list_copy( job->list_audio ); + job_copy->list_attachment = hb_attachment_list_copy( job->list_attachment ); + job_copy->metadata = hb_metadata_copy( job->metadata ); + + if ( job->file ) + job_copy->file = strdup( job->file ); + if ( job->advanced_opts ) + job_copy->advanced_opts = strdup( job->advanced_opts ); job_copy->h = h; job_copy->pause = h->pause_lock; /* Copy the job filter list */ - if( job->list_filter ) - { - int i; - int filter_count = hb_list_count( job->list_filter ); - job_copy->list_filter = hb_list_init(); - for( i = 0; i < filter_count; i++ ) - { - /* - * Copy the filters, since the MacGui reuses the global filter objects - * meaning that queued up jobs overwrite the previous filter settings. - * In reality, settings is probably the only field that needs duplicating - * since it's the only value that is ever changed. But name is duplicated - * as well for completeness. Not copying private_data since it gets - * created for each job in renderInit. - */ - hb_filter_object_t * filter = hb_list_item( job->list_filter, i ); - hb_filter_object_t * filter_copy = hb_filter_copy( filter ); - hb_list_add( job_copy->list_filter, filter_copy ); - } - } + job_copy->list_filter = hb_filter_list_copy( job->list_filter ); /* Add the job to the list */ hb_list_add( h->jobs, job_copy ); @@ -1638,37 +1481,6 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) } /** - * Clean up the job structure so that is is ready for setting up a new job. - * Should be called by front-ends after hb_add(). - */ -void hb_reset_job( hb_job_t * job ) -{ - hb_audio_t *audio; - hb_subtitle_t *subtitle; - hb_filter_object_t *filter; - - // clean up audio list - while( ( audio = hb_list_item( job->list_audio, 0 ) ) ) - { - hb_list_rem( job->list_audio, audio ); - free( audio ); - } - // clean up subtitle list - while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) ) - { - hb_list_rem( job->list_subtitle, subtitle ); - free( subtitle ); - } - // clean up filter list - while( ( filter = hb_list_item( job->list_filter, 0 ) ) ) - { - hb_list_rem( job->list_filter, filter ); - free( filter->settings ); - free( filter ); - } -} - -/** * Removes a job from the job list. * @param h Handle to hb_handle_t. * @param job Handle to hb_job_t. @@ -1831,17 +1643,12 @@ void hb_close( hb_handle_t ** _h ) hb_thread_close( &h->main_thread ); - while( ( title = hb_list_item( h->list_title, 0 ) ) ) + while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) ) { - hb_list_rem( h->list_title, title ); - if( title->job ) - { - hb_reset_job( title->job ); - } - free( title->job ); + hb_list_rem( h->title_set.list_title, title ); hb_title_close( &title ); } - hb_list_close( &h->list_title ); + hb_list_close( &h->title_set.list_title ); hb_list_close( &h->jobs ); hb_lock_close( &h->state_lock ); @@ -1925,9 +1732,9 @@ static void thread_func( void * _h ) hb_title_t * title; hb_remove_previews( h ); - while( ( title = hb_list_item( h->list_title, 0 ) ) ) + while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) ) { - hb_list_rem( h->list_title, title ); + hb_list_rem( h->title_set.list_title, title ); hb_title_close( &title ); } @@ -1936,7 +1743,7 @@ static void thread_func( void * _h ) else { hb_log( "libhb: scan thread found %d valid title(s)", - hb_list_count( h->list_title ) ); + hb_list_count( h->title_set.list_title ) ); } hb_lock( h->state_lock ); h->state.state = HB_STATE_SCANDONE; //originally state.state @@ -2024,29 +1831,6 @@ int hb_get_instance_id( hb_handle_t * h ) } /** - * Returns the title with the given title index. - * @param h Handle to hb_handle_t - * @param title_index the index of the title to get - * @returns The requested title - */ -hb_title_t * hb_get_title_by_index( hb_handle_t * h, int title_index ) -{ - hb_title_t * title; - int i; - int count = hb_list_count( h->list_title ); - for (i = 0; i < count; i++) - { - title = hb_list_item( h->list_title, i ); - if (title->index == title_index) - { - return title; - } - } - - return NULL; -} - -/** * Sets the current state. * @param h Handle to hb_handle_t * @param s Handle to new hb_state_t diff --git a/libhb/hb.h b/libhb/hb.h index da2311834..825032cfb 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -54,21 +54,23 @@ uint64_t hb_first_duration( hb_handle_t * ); Returns the list of valid titles detected by the latest scan. */ hb_list_t * hb_get_titles( hb_handle_t * ); +/* hb_get_title_set() + Returns the title set which contains a list of valid titles detected + by the latest scan and title set data. */ +hb_title_set_t * hb_get_title_set( hb_handle_t * ); + /* hb_detect_comb() Analyze a frame for interlacing artifacts, returns true if they're found. Taken from Thomas Oestreich's 32detect filter in the Transcode project. */ 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 ); +// 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 ); -void hb_get_preview_by_index( hb_handle_t *, int, int, uint8_t * ); -void hb_get_preview( hb_handle_t *, hb_title_t *, int, +void hb_get_preview( hb_handle_t *, hb_job_t *, int, uint8_t * ); void hb_set_size( hb_job_t *, double ratio, int pixels ); -void hb_set_anamorphic_size_by_index( hb_handle_t *, int, - int *output_width, int *output_height, - int *output_par_width, int *output_par_height ); void hb_set_anamorphic_size( hb_job_t *, int *output_width, int *output_height, int *output_par_width, int *output_par_height ); @@ -83,7 +85,11 @@ void hb_set_chapter_name( hb_handle_t *, int, int, const char * ); void hb_set_job( hb_handle_t *, int, hb_job_t * ); void hb_add( hb_handle_t *, hb_job_t * ); void hb_rem( hb_handle_t *, hb_job_t * ); -void hb_reset_job( hb_job_t * job ); + +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 ); void hb_start( hb_handle_t * ); void hb_pause( hb_handle_t * ); diff --git a/libhb/internal.h b/libhb/internal.h index caa2e7189..1c02ffe85 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -228,7 +228,7 @@ static inline hb_buffer_t * hb_video_buffer_init( int width, int height ) hb_thread_t * hb_update_init( int * build, char * version ); hb_thread_t * hb_scan_init( hb_handle_t *, volatile int * die, const char * path, int title_index, - hb_list_t * list_title, int preview_count, + hb_title_set_t * title_set, int preview_count, int store_previews, uint64_t min_duration ); hb_thread_t * hb_work_init( hb_list_t * jobs, volatile int * die, int * error, hb_job_t ** job ); @@ -266,7 +266,7 @@ extern const hb_muxer_t hb_demux[]; /*********************************************************************** * decmetadata.c **********************************************************************/ -extern void decmetadata( hb_title_t *title ); +extern int decmetadata( hb_title_t *title ); /*********************************************************************** * batch.c diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c index 6587a4dac..d5d9c7a92 100644 --- a/libhb/muxcommon.c +++ b/libhb/muxcommon.c @@ -441,7 +441,6 @@ static void mux_loop( void * _w ) hb_work_object_t * hb_muxer_init( hb_job_t * job ) { - hb_title_t * title = job->title; int i; hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 ); hb_work_object_t * w; @@ -490,9 +489,9 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job ) add_mux_track( mux, job->mux_data, 1 ); muxer->done = &muxer->private_data->mux->done; - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - hb_audio_t *audio = hb_list_item( title->list_audio, i ); + hb_audio_t *audio = hb_list_item( job->list_audio, i ); w = hb_get_work( WORK_MUX ); w->private_data = calloc( sizeof( hb_work_private_t ), 1 ); @@ -507,9 +506,9 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job ) w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY ); } - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, i ); + hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, i ); if (subtitle->config.dest != PASSTHRUSUB) continue; diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index addd800de..2b629bc49 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -59,7 +59,6 @@ static uint8_t * create_flac_header( uint8_t *data, int size ) static int MKVInit( hb_mux_object_t * m ) { hb_job_t * job = m->job; - hb_title_t * title = job->title; hb_audio_t * audio; hb_mux_data_t * mux_data; @@ -197,9 +196,9 @@ static int MKVInit( hb_mux_object_t * m ) mux_data->track = mk_createTrack(m->file, track); /* add the audio tracks */ - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); mux_data = calloc(1, sizeof( hb_mux_data_t ) ); audio->priv.mux_data = mux_data; @@ -328,14 +327,14 @@ static int MKVInit( hb_mux_object_t * m ) "custom colors: OFF, tridx: 0000, " "colors: 000000, 000000, 000000, 000000\n"; - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { hb_subtitle_t * subtitle; uint32_t rgb[16]; char subidx[2048]; int len; - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if (subtitle->config.dest != PASSTHRUSUB) continue; @@ -400,7 +399,7 @@ static int MKVInit( hb_mux_object_t * m ) if (need_fonts) { - hb_list_t * list_attachment = job->title->list_attachment; + hb_list_t * list_attachment = job->list_attachment; int i; for ( i = 0; i < hb_list_count(list_attachment); i++ ) { @@ -437,7 +436,6 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, { ogg_packet *op = NULL; hb_job_t * job = m->job; - hb_title_t * title = job->title; uint64_t timecode = 0; hb_chapter_t *chapter_data; char tmp_buffer[1024]; @@ -457,7 +455,7 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, { mux_data->current_chapter = buf->s.new_chap - 2; } - chapter_data = hb_list_item( title->list_chapter, + chapter_data = hb_list_item( job->list_chapter, mux_data->current_chapter++ ); tmp_buffer[0] = '\0'; @@ -556,7 +554,6 @@ static int MKVEnd( hb_mux_object_t * m ) { hb_job_t *job = m->job; hb_mux_data_t *mux_data = job->mux_data; - hb_title_t *title = job->title; hb_chapter_t *chapter_data; char tmp_buffer[1024]; char *string = tmp_buffer; @@ -569,7 +566,7 @@ static int MKVEnd( hb_mux_object_t * m ) return 0; } - chapter_data = hb_list_item( title->list_chapter, mux_data->current_chapter++ ); + chapter_data = hb_list_item( job->list_chapter, mux_data->current_chapter++ ); if(job->chapter_markers) { @@ -588,29 +585,62 @@ static int MKVEnd( hb_mux_object_t * m ) mk_createChapterSimple(m->file, mux_data->prev_chapter_tc, mux_data->prev_chapter_tc, string); } - if( title->metadata ) + if( job->metadata ) { - hb_metadata_t *md = title->metadata; + hb_metadata_t *md = job->metadata; hb_deep_log( 2, "Writing Metadata to output file..."); - mk_createTagSimple( m->file, MK_TAG_TITLE, md->name ); - mk_createTagSimple( m->file, "ARTIST", md->artist ); - mk_createTagSimple( m->file, "COMPOSER", md->composer ); - mk_createTagSimple( m->file, MK_TAG_SYNOPSIS, md->comment ); - mk_createTagSimple( m->file, "DATE_RELEASED", md->release_date ); - // mk_createTagSimple( m->file, "", md->album ); - mk_createTagSimple( m->file, MK_TAG_GENRE, md->genre ); + if ( md->name ) + { + mk_createTagSimple( m->file, MK_TAG_TITLE, md->name ); + } + if ( md->artist ) + { + mk_createTagSimple( m->file, "ARTIST", md->artist ); + } + if ( md->album_artist ) + { + mk_createTagSimple( m->file, "DIRECTOR", md->album_artist ); + } + if ( md->composer ) + { + mk_createTagSimple( m->file, "COMPOSER", md->composer ); + } + if ( md->release_date ) + { + mk_createTagSimple( m->file, "DATE_RELEASED", md->release_date ); + } + if ( md->comment ) + { + mk_createTagSimple( m->file, "SUMMARY", md->comment ); + } + if ( !md->name && md->album ) + { + mk_createTagSimple( m->file, MK_TAG_TITLE, md->album ); + } + if ( md->genre ) + { + mk_createTagSimple( m->file, MK_TAG_GENRE, md->genre ); + } + if ( md->description ) + { + mk_createTagSimple( m->file, "DESCRIPTION", md->description ); + } + if ( md->long_description ) + { + mk_createTagSimple( m->file, "SYNOPSIS", md->long_description ); + } } // Update and track private data that can change during // encode. int i; - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { mk_Track * track; hb_audio_t * audio; - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); track = audio->priv.mux_data->track; switch (audio->config.out.codec & HB_ACODEC_MASK) diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index d21e4b767..f1380dc18 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -262,9 +262,9 @@ static int MP4Init( hb_mux_object_t * m ) } /* add the audio tracks */ - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); mux_data = calloc(1, sizeof( hb_mux_data_t ) ); audio->priv.mux_data = mux_data; @@ -464,7 +464,7 @@ static int MP4Init( hb_mux_object_t * m ) /* Set the language for this track */ MP4SetTrackLanguage(m->file, mux_data->track, audio->config.lang.iso639_2); - if( hb_list_count( title->list_audio ) > 1 ) + if( hb_list_count( job->list_audio ) > 1 ) { /* Set the audio track alternate group */ MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1); @@ -944,7 +944,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, duration = m->sum_dur - m->chapter_duration + offset; if ( duration >= (90000*3)/2 ) { - chapter = hb_list_item( m->job->title->list_chapter, + chapter = hb_list_item( m->job->list_chapter, buf->s.new_chap - 2 ); MP4AddChapter( m->file, @@ -1248,7 +1248,6 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, static int MP4End( hb_mux_object_t * m ) { hb_job_t * job = m->job; - hb_title_t * title = job->title; // Flush the delayed frame if ( m->delay_buf ) @@ -1264,7 +1263,7 @@ static int MP4End( hb_mux_object_t * m ) if ( duration >= (90000*3)/2 ) { - chapter = hb_list_item( m->job->title->list_chapter, + chapter = hb_list_item( m->job->list_chapter, m->current_chapter - 1 ); MP4AddChapter( m->file, @@ -1293,9 +1292,9 @@ static int MP4End( hb_mux_object_t * m ) /* * Write the MP4 iTunes metadata if we have any metadata */ - if( title->metadata ) + if( job->metadata ) { - hb_metadata_t *md = title->metadata; + hb_metadata_t *md = job->metadata; const MP4Tags* tags; hb_deep_log( 2, "Writing Metadata to output file..."); @@ -1306,28 +1305,60 @@ static int MP4End( hb_mux_object_t * m ) MP4TagsFetch( tags, m->file ); /* populate */ - if( strlen( md->name )) + if( md->name ) MP4TagsSetName( tags, md->name ); - if( strlen( md->artist )) + if( md->artist ) MP4TagsSetArtist( tags, md->artist ); - if( strlen( md->composer )) + if( md->composer ) MP4TagsSetComposer( tags, md->composer ); - if( strlen( md->comment )) + if( md->comment ) MP4TagsSetComments( tags, md->comment ); - if( strlen( md->release_date )) + if( md->release_date ) MP4TagsSetReleaseDate( tags, md->release_date ); - if( strlen( md->album )) + if( md->album ) MP4TagsSetAlbum( tags, md->album ); - if( strlen( md->genre )) + if( md->album_artist ) + MP4TagsSetAlbumArtist( tags, md->album_artist ); + if( md->genre ) MP4TagsSetGenre( tags, md->genre ); + if( md->description ) + MP4TagsSetDescription( tags, md->description ); + if( md->long_description ) + MP4TagsSetLongDescription( tags, md->long_description ); - if( md->coverart ) + if( md->list_coverart ) { - MP4TagArtwork art; - art.data = md->coverart; - art.size = md->coverart_size; - art.type = MP4_ART_UNDEFINED; // delegate typing to libmp4v2 - MP4TagsAddArtwork( tags, &art ); + hb_coverart_t * coverart; + int ii; + + for ( ii = 0; ii < hb_list_count( md->list_coverart ); ii++ ) + { + coverart = hb_list_item( md->list_coverart, ii ); + MP4TagArtwork art; + int type; + switch ( coverart->type ) + { + case HB_ART_BMP: + type = MP4_ART_BMP; + break; + case HB_ART_GIF: + type = MP4_ART_GIF; + break; + case HB_ART_JPEG: + type = MP4_ART_JPEG; + break; + case HB_ART_PNG: + type = MP4_ART_PNG; + break; + default: + type = MP4_ART_UNDEFINED; + break; + } + art.data = coverart->data; + art.size = coverart->size; + art.type = type; + MP4TagsAddArtwork( tags, &art ); + } } /* push data to MP4 file */ diff --git a/libhb/reader.c b/libhb/reader.c index 8148e6590..d5c937422 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -386,12 +386,12 @@ void ReadLoop( void * _w ) * a media chapter that got merged, we'll stop ripping too early. */ int start = r->job->chapter_start; - hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 ); + hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 ); chapter_end = chap->index; if (start > 1) { - chap = hb_list_item( r->title->list_chapter, start - 1 ); + chap = hb_list_item( r->job->list_chapter, start - 1 ); start = chap->index; } /* end chapter mapping XXX */ @@ -453,12 +453,12 @@ void ReadLoop( void * _w ) * end chapter so that we end at the right time. */ int start = r->job->chapter_start; - hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 ); + hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 ); chapter_end = chap->index; if (start > 1) { - chap = hb_list_item( r->title->list_chapter, start - 1 ); + chap = hb_list_item( r->job->list_chapter, start - 1 ); start = chap->index; } @@ -670,14 +670,14 @@ void ReadLoop( void * _w ) push_buf( r, r->job->fifo_mpeg2, hb_buffer_init(0) ); hb_audio_t *audio; - for( n = 0; (audio = hb_list_item( r->job->title->list_audio, n)); ++n ) + for( n = 0; (audio = hb_list_item( r->job->list_audio, n)); ++n ) { if ( audio->priv.fifo_in ) push_buf( r, audio->priv.fifo_in, hb_buffer_init(0) ); } hb_subtitle_t *subtitle; - for( n = 0; (subtitle = hb_list_item( r->job->title->list_subtitle, n)); ++n ) + for( n = 0; (subtitle = hb_list_item( r->job->list_subtitle, n)); ++n ) { if ( subtitle->fifo_in && subtitle->source == VOBSUB) push_buf( r, subtitle->fifo_in, hb_buffer_init(0) ); @@ -780,11 +780,11 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id ) } } - count = hb_list_count( title->list_subtitle ); + count = hb_list_count( job->list_subtitle ); count = count > 99 ? 99 : count; for( i = n = 0; i < count; i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if (id == subtitle->id) { /* pass the subtitles to be processed */ @@ -798,9 +798,9 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id ) if( !job->indepth_scan ) { - for( i = n = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = n = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); if( id == audio->id ) { r->fifos[n++] = audio->priv.fifo_in; diff --git a/libhb/rendersub.c b/libhb/rendersub.c index 568b7d1b0..c9e9f02cf 100644 --- a/libhb/rendersub.c +++ b/libhb/rendersub.c @@ -441,7 +441,7 @@ static int ssa_init( hb_filter_object_t * filter, ass_set_message_cb( pv->ssa, ssa_log, NULL ); // Load embedded fonts - hb_list_t * list_attachment = init->job->title->list_attachment; + hb_list_t * list_attachment = init->job->list_attachment; int i; for ( i = 0; i < hb_list_count(list_attachment); i++ ) { @@ -678,9 +678,9 @@ static int hb_rendersub_init( hb_filter_object_t * filter, } // Find the subtitle we need - for( ii = 0; ii < hb_list_count(init->job->title->list_subtitle); ii++ ) + for( ii = 0; ii < hb_list_count(init->job->list_subtitle); ii++ ) { - subtitle = hb_list_item( init->job->title->list_subtitle, ii ); + subtitle = hb_list_item( init->job->list_subtitle, ii ); if( subtitle && subtitle->config.dest == RENDERSUB ) { // Found it diff --git a/libhb/scan.c b/libhb/scan.c index 10ed35391..0163af406 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -18,7 +18,7 @@ typedef struct char * path; int title_index; - hb_list_t * list_title; + hb_title_set_t * title_set; hb_bd_t * bd; hb_dvd_t * dvd; @@ -51,7 +51,7 @@ static const char *aspect_to_string( double aspect ) hb_thread_t * hb_scan_init( hb_handle_t * handle, volatile int * die, const char * path, int title_index, - hb_list_t * list_title, int preview_count, + hb_title_set_t * title_set, int preview_count, int store_previews, uint64_t min_duration ) { hb_scan_t * data = calloc( sizeof( hb_scan_t ), 1 ); @@ -60,7 +60,7 @@ hb_thread_t * hb_scan_init( hb_handle_t * handle, volatile int * die, data->die = die; data->path = strdup( path ); data->title_index = title_index; - data->list_title = list_title; + data->title_set = title_set; data->preview_count = preview_count; data->store_previews = store_previews; @@ -88,7 +88,8 @@ static void ScanFunc( void * _data ) if( data->title_index ) { /* Scan this title only */ - hb_list_add( data->list_title, hb_bd_title_scan( data->bd, + hb_list_add( data->title_set->list_title, + hb_bd_title_scan( data->bd, data->title_index, 0 ) ); } else @@ -96,10 +97,12 @@ static void ScanFunc( void * _data ) /* Scan all titles */ for( i = 0; i < hb_bd_title_count( data->bd ); i++ ) { - hb_list_add( data->list_title, hb_bd_title_scan( data->bd, + hb_list_add( data->title_set->list_title, + hb_bd_title_scan( data->bd, i + 1, data->min_title_duration ) ); } - feature = hb_bd_main_feature( data->bd, data->list_title ); + feature = hb_bd_main_feature( data->bd, + data->title_set->list_title ); } } else if( ( data->dvd = hb_dvd_init( data->path ) ) ) @@ -109,7 +112,8 @@ static void ScanFunc( void * _data ) if( data->title_index ) { /* Scan this title only */ - hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd, + hb_list_add( data->title_set->list_title, + hb_dvd_title_scan( data->dvd, data->title_index, 0 ) ); } else @@ -117,10 +121,12 @@ static void ScanFunc( void * _data ) /* Scan all titles */ for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ ) { - hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd, + hb_list_add( data->title_set->list_title, + hb_dvd_title_scan( data->dvd, i + 1, data->min_title_duration ) ); } - feature = hb_dvd_main_feature( data->dvd, data->list_title ); + feature = hb_dvd_main_feature( data->dvd, + data->title_set->list_title ); } } else if ( ( data->batch = hb_batch_init( data->path ) ) ) @@ -131,7 +137,7 @@ static void ScanFunc( void * _data ) title = hb_batch_title_scan( data->batch, data->title_index ); if ( title ) { - hb_list_add( data->list_title, title ); + hb_list_add( data->title_set->list_title, title ); } } else @@ -144,7 +150,7 @@ static void ScanFunc( void * _data ) title = hb_batch_title_scan( data->batch, i + 1 ); if ( title != NULL ) { - hb_list_add( data->list_title, title ); + hb_list_add( data->title_set->list_title, title ); } } } @@ -156,7 +162,7 @@ static void ScanFunc( void * _data ) { title = hb_stream_title_scan( data->stream, title ); if ( title ) - hb_list_add( data->list_title, title ); + hb_list_add( data->title_set->list_title, title ); } else { @@ -166,7 +172,7 @@ static void ScanFunc( void * _data ) } } - for( i = 0; i < hb_list_count( data->list_title ); ) + for( i = 0; i < hb_list_count( data->title_set->list_title ); ) { int j; hb_state_t state; @@ -176,7 +182,7 @@ static void ScanFunc( void * _data ) { goto finish; } - title = hb_list_item( data->list_title, i ); + title = hb_list_item( data->title_set->list_title, i ); #define p state.param.scanning /* Update the UI */ @@ -185,7 +191,7 @@ static void ScanFunc( void * _data ) p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : data->bd ? hb_bd_title_count( data->bd ) : data->batch ? hb_batch_title_count( data->batch ) : - hb_list_count(data->list_title); + hb_list_count(data->title_set->list_title); hb_set_state( data->h, &state ); #undef p @@ -194,7 +200,7 @@ static void ScanFunc( void * _data ) if( !DecodePreviews( data, title ) ) { /* TODO: free things */ - hb_list_rem( data->list_title, title ); + hb_list_rem( data->title_set->list_title, title ); for( j = 0; j < hb_list_count( title->list_audio ); j++) { audio = hb_list_item( title->list_audio, j ); @@ -247,64 +253,16 @@ static void ScanFunc( void * _data ) i++; } - /* Init jobs templates */ - for( i = 0; i < hb_list_count( data->list_title ); i++ ) - { - hb_job_t * job; - - title = hb_list_item( data->list_title, i ); - job = calloc( sizeof( hb_job_t ), 1 ); - title->job = job; - - job->title = title; - job->feature = feature; + data->title_set->feature = feature; - /* Set defaults settings */ - job->chapter_start = 1; - job->chapter_end = hb_list_count( title->list_chapter ); - - /* Autocrop by default. Gnark gnark */ - memcpy( job->crop, title->crop, 4 * sizeof( int ) ); - - /* Preserve a source's pixel aspect, if it's available. */ - if( title->pixel_aspect_width && title->pixel_aspect_height ) - { - job->anamorphic.par_width = title->pixel_aspect_width; - job->anamorphic.par_height = title->pixel_aspect_height; - } - - if( title->aspect != 0 && title->aspect != 1. && - !job->anamorphic.par_width && !job->anamorphic.par_height) - { - hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height, - (int)(title->aspect * title->height + 0.5), title->width ); - } - - job->width = title->width - job->crop[2] - job->crop[3]; - hb_fix_aspect( job, HB_KEEP_WIDTH ); - if( job->height > title->height - job->crop[0] - job->crop[1] ) - { - job->height = title->height - job->crop[0] - job->crop[1]; - hb_fix_aspect( job, HB_KEEP_HEIGHT ); - } - - hb_log( "scan: title (%d) job->width:%d, job->height:%d", - i, job->width, job->height ); - - job->keep_ratio = 1; - - job->vcodec = HB_VCODEC_FFMPEG_MPEG4; - job->vquality = -1.0; - job->vbitrate = 1000; - job->pass = 0; - job->vrate = title->rate; - job->vrate_base = title->rate_base; - - job->list_audio = hb_list_init(); - job->list_subtitle = hb_list_init(); - job->list_filter = hb_list_init(); - - job->mux = HB_MUX_MP4; + /* Mark title scan complete and init jobs */ + for( i = 0; i < hb_list_count( data->title_set->list_title ); i++ ) + { + title = hb_list_item( data->title_set->list_title, i ); + title->flags |= HBTF_SCAN_COMPLETE; +#if defined(HB_TITLE_JOBS) + title->job = hb_job_init( title ); +#endif } finish: diff --git a/libhb/stream.c b/libhb/stream.c index ede9f33d3..503e296dc 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -960,11 +960,10 @@ hb_stream_t * hb_bd_stream_open( hb_title_t *title ) update_ts_streams( d, pid, 0, stream_type, S, NULL ); } - // When scanning, title->job == NULL. We don't need to wait for - // a PCR when scanning. In fact, it trips us up on the first - // preview of every title since we would have to read quite a - // lot of data before finding the PCR. - if ( title->job ) + // We don't need to wait for a PCR when scanning. In fact, it + // trips us up on the first preview of every title since we would + // have to read quite a lot of data before finding the PCR. + if ( !(title->flags & HBTF_SCAN_COMPLETE) ) { /* BD has PCRs, but the BD index always points to a packet * after a PCR packet, so we will not see the initial PCR @@ -2774,7 +2773,6 @@ int decode_program_map(hb_stream_t* stream) stream->pmt_info.PCR_PID = bits_get(&bb, 13); bits_get(&bb, 4); int program_info_length = bits_get(&bb, 12); - int i; for (i = 0; i < program_info_length - 2; ) { @@ -5371,6 +5369,7 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id static char *get_ffmpeg_metadata_value( AVDictionary *m, char *key ) { AVDictionaryEntry *tag = NULL; + while ( (tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)) ) { if ( !strcmp( key, tag->key ) ) @@ -5425,6 +5424,64 @@ static void add_ffmpeg_attachment( hb_title_t *title, hb_stream_t *stream, int i hb_list_add(title->list_attachment, attachment); } +static int ffmpeg_decmetadata( AVDictionary *m, hb_title_t *title ) +{ + int result = 0; + AVDictionaryEntry *tag = NULL; + while ( (tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)) ) + { + if ( !strcasecmp( "TITLE", tag->key ) ) + { + hb_metadata_set_name(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "ARTIST", tag->key ) ) + { + hb_metadata_set_artist(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "DIRECTOR", tag->key ) || + !strcasecmp( "album_artist", tag->key ) ) + { + hb_metadata_set_album_artist(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "COMPOSER", tag->key ) ) + { + hb_metadata_set_composer(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "DATE_RELEASED", tag->key ) || + !strcasecmp( "date", tag->key ) ) + { + hb_metadata_set_release_date(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "SUMMARY", tag->key ) || + !strcasecmp( "comment", tag->key ) ) + { + hb_metadata_set_comment(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "GENRE", tag->key ) ) + { + hb_metadata_set_genre(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "DESCRIPTION", tag->key ) ) + { + hb_metadata_set_description(title->metadata, tag->value); + result = 1; + } + else if ( !strcasecmp( "SYNOPSIS", tag->key ) ) + { + hb_metadata_set_long_description(title->metadata, tag->value); + result = 1; + } + } + return result; +} + static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) { AVFormatContext *ic = stream->ffmpeg_ic; @@ -5520,16 +5577,20 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) chapter->seconds = ( seconds % 60 ); tag = av_dict_get( m->metadata, "title", NULL, 0 ); - /* Ignore generic chapter names set by MakeMKV ("Chapter 00" etc.). + /* Ignore generic chapter names set by MakeMKV + * ("Chapter 00" etc.). * Our default chapter names are better. */ if( tag && tag->value && - ( strncmp( "Chapter ", tag->value, 8 ) || strlen( tag->value ) > 11 ) ) + ( strncmp( "Chapter ", tag->value, 8 ) || + strlen( tag->value ) > 11 ) ) { - strcpy( chapter->title, tag->value ); + hb_chapter_set_title( chapter, tag->value ); } else { - sprintf( chapter->title, "Chapter %d", chapter->index ); + char chapter_title[80]; + sprintf( chapter_title, "Chapter %d", chapter->index ); + hb_chapter_set_title( chapter, chapter_title ); } hb_deep_log( 2, "Added chapter %i, name='%s', dur=%"PRIu64", (%02i:%02i:%02i)", @@ -5543,7 +5604,11 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) /* * Fill the metadata. */ - decmetadata( title ); + // JJJ: is this necessary? can we just get this metadata from libav api's? + if (!decmetadata( title )) + { + ffmpeg_decmetadata( ic->metadata, title ); + } if( hb_list_count( title->list_chapter ) == 0 ) { @@ -5787,16 +5852,25 @@ hb_buffer_t * hb_ffmpeg_read( hb_stream_t *stream ) static int ffmpeg_seek( hb_stream_t *stream, float frac ) { AVFormatContext *ic = stream->ffmpeg_ic; + int res; if ( frac > 0. ) { int64_t pos = (double)stream->ffmpeg_ic->duration * (double)frac + ffmpeg_initial_timestamp( stream ); - avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD); + res = avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD); + if (res < 0) + { + hb_error("avformat_seek_file failed"); + } } else { int64_t pos = ffmpeg_initial_timestamp( stream ); - avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD); + res = avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD); + if (res < 0) + { + hb_error("avformat_seek_file failed"); + } } stream->need_keyframe = 1; return 1; diff --git a/libhb/sync.c b/libhb/sync.c index c3e4c37a1..f416d1664 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -167,7 +167,7 @@ hb_work_object_t * hb_sync_init( hb_job_t * job ) duration = 0; for( i = job->chapter_start; i <= job->chapter_end; i++ ) { - chapter = hb_list_item( title->list_chapter, i - 1 ); + chapter = hb_list_item( job->list_chapter, i - 1 ); duration += chapter->duration; } } @@ -179,7 +179,7 @@ hb_work_object_t * hb_sync_init( hb_job_t * job ) /* Initialize libsamplerate for every audio track we have */ if ( ! job->indepth_scan ) { - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { InitAudio( job, pv->common, i ); } @@ -892,7 +892,6 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i ) { hb_work_object_t * w; hb_work_private_t * pv; - hb_title_t * title = job->title; hb_sync_audio_t * sync; pv = calloc( 1, sizeof( hb_work_private_t ) ); @@ -905,7 +904,7 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i ) w = hb_get_work( WORK_SYNC_AUDIO ); w->private_data = pv; - w->audio = hb_list_item( title->list_audio, i ); + w->audio = hb_list_item( job->list_audio, i ); w->fifo_in = w->audio->priv.fifo_raw; if ( w->audio->config.out.codec & HB_ACODEC_PASS_FLAG ) diff --git a/libhb/work.c b/libhb/work.c index 277ebf033..030920c59 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -389,9 +389,9 @@ void hb_display_job_info( hb_job_t * job ) job->select_subtitle_config.default_track ? ", Default" : "" ); } - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if( subtitle ) { @@ -425,9 +425,9 @@ void hb_display_job_info( hb_job_t * job ) if( !job->indepth_scan ) { - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); hb_log( " * audio track %d", audio->config.out.track ); @@ -529,6 +529,7 @@ static void do_job( hb_job_t * job ) hb_work_object_t * w; hb_work_object_t * sync; hb_work_object_t * muxer; + hb_work_object_t *reader = hb_get_work(WORK_READER); hb_interjob_t * interjob; hb_audio_t * audio; @@ -563,21 +564,25 @@ static void do_job( hb_job_t * job ) { interjob->select_subtitle->config.force = 0; } - for( i = 0; i < hb_list_count(title->list_subtitle); ) + for( i = 0; i < hb_list_count( job->list_subtitle ); ) { - if( ( subtitle = hb_list_item( title->list_subtitle, i ) ) ) + subtitle = hb_list_item( job->list_subtitle, i ); + if( subtitle ) { - /* Remove the scanned subtitle from the list if it would result in: + /* Remove the scanned subtitle from the list if + * it would result in: * - an emty track (forced and no forced hits) * - an identical, duplicate subtitle track: * -> both (or neither) are forced * -> subtitle is not forced but all its hits are forced */ if( ( interjob->select_subtitle->id == subtitle->id ) && - ( ( subtitle->config.force && interjob->select_subtitle->forced_hits == 0 ) || + ( ( subtitle->config.force && + interjob->select_subtitle->forced_hits == 0 ) || ( subtitle->config.force == interjob->select_subtitle->config.force ) || - ( subtitle->config.force == 0 && interjob->select_subtitle->hits == interjob->select_subtitle->forced_hits ) ) ) + ( !subtitle->config.force && + interjob->select_subtitle->hits == interjob->select_subtitle->forced_hits ) ) ) { - hb_list_rem( title->list_subtitle, subtitle ); + hb_list_rem( job->list_subtitle, subtitle ); free( subtitle ); continue; } @@ -602,13 +607,13 @@ static void do_job( hb_job_t * job ) if (job->pass == 0 || job->pass == 2) { // final pass, interjob->select_subtitle is no longer needed - hb_list_insert(title->list_subtitle, 0, interjob->select_subtitle); + hb_list_insert(job->list_subtitle, 0, interjob->select_subtitle); interjob->select_subtitle = NULL; } else { // this is not the final pass, so we need to copy it instead - hb_list_insert(title->list_subtitle, 0, hb_subtitle_copy(interjob->select_subtitle)); + hb_list_insert(job->list_subtitle, 0, hb_subtitle_copy(interjob->select_subtitle)); } } @@ -616,10 +621,9 @@ static void do_job( hb_job_t * job ) { // Sanitize subtitles uint8_t one_burned = 0; - for( i = 0; i < hb_list_count( title->list_subtitle ); ) + for( i = 0; i < hb_list_count( job->list_subtitle ); ) { - subtitle = hb_list_item( title->list_subtitle, i ); - + subtitle = hb_list_item( job->list_subtitle, i ); if ( subtitle->config.dest == RENDERSUB ) { if ( one_burned ) @@ -627,7 +631,7 @@ static void do_job( hb_job_t * job ) if ( !hb_subtitle_can_pass(subtitle->source, job->mux) ) { hb_log( "More than one subtitle burn-in requested, dropping track %d.", i ); - hb_list_rem( title->list_subtitle, subtitle ); + hb_list_rem( job->list_subtitle, subtitle ); free( subtitle ); continue; } @@ -661,7 +665,7 @@ static void do_job( hb_job_t * job ) else { hb_log( "Subtitle pass-thru requested and input track is not compatible with container. One track already burned, dropping track %d.", i ); - hb_list_rem( title->list_subtitle, subtitle ); + hb_list_rem( job->list_subtitle, subtitle ); free( subtitle ); continue; } @@ -697,9 +701,9 @@ static void do_job( hb_job_t * job ) init.height = title->height; init.par_width = job->anamorphic.par_width; init.par_height = job->anamorphic.par_height; - memcpy(init.crop, title->crop, sizeof(int[4])); - init.vrate_base = title->rate_base; - init.vrate = title->rate; + memcpy(init.crop, job->crop, sizeof(int[4])); + init.vrate_base = job->vrate_base; + init.vrate = job->vrate; init.pfr_vrate_base = job->pfr_vrate_base; init.pfr_vrate = job->pfr_vrate; init.cfr = 0; @@ -720,7 +724,7 @@ static void do_job( hb_job_t * job ) job->height = init.height; job->anamorphic.par_width = init.par_width; job->anamorphic.par_height = init.par_height; - memcpy(title->crop, init.crop, sizeof(int[4])); + memcpy(job->crop, init.crop, sizeof(int[4])); job->vrate_base = init.vrate_base; job->vrate = init.vrate; job->pfr_vrate_base = init.pfr_vrate_base; @@ -761,18 +765,18 @@ static void do_job( hb_job_t * job ) if (!job->indepth_scan) { // apply Auto Passthru settings - hb_autopassthru_apply_settings(job, title); + hb_autopassthru_apply_settings(job); // sanitize audio settings - for (i = 0; i < hb_list_count(title->list_audio);) + for (i = 0; i < hb_list_count(job->list_audio);) { - audio = hb_list_item(title->list_audio, i); + audio = hb_list_item(job->list_audio, i); if (audio->config.out.codec == HB_ACODEC_AUTO_PASS) { // Auto Passthru should have been handled above // remove track to avoid a crash hb_log("Auto Passthru error, dropping track %d", audio->config.out.track); - hb_list_rem(title->list_audio, audio); + hb_list_rem(job->list_audio, audio); free(audio); continue; } @@ -782,7 +786,7 @@ static void do_job( hb_job_t * job ) { hb_log("Passthru requested and input codec is not the same as output codec for track %d, dropping track", audio->config.out.track); - hb_list_rem(title->list_audio, audio); + hb_list_rem(job->list_audio, audio); free(audio); continue; } @@ -796,9 +800,9 @@ static void do_job( hb_job_t * job ) int best_bitrate = 0; int best_samplerate = 0; - for (i = 0; i < hb_list_count(title->list_audio); i++) + for (i = 0; i < hb_list_count(job->list_audio); i++) { - audio = hb_list_item(title->list_audio, i); + audio = hb_list_item(job->list_audio, i); /* set up the audio work structures */ audio->priv.fifo_raw = hb_fifo_init(FIFO_SMALL, FIFO_SMALL_WAKE); @@ -999,9 +1003,9 @@ static void do_job( hb_job_t * job ) w->fifo_in = job->fifo_mpeg2; w->fifo_out = job->fifo_raw; - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if( subtitle ) { @@ -1081,9 +1085,9 @@ static void do_job( hb_job_t * job ) hb_list_add( job->list_work, w ); - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); /* * Audio Decoder Thread @@ -1140,7 +1144,6 @@ static void do_job( hb_job_t * job ) hb_display_job_info( job ); /* Init read & write threads */ - hb_work_object_t *reader = hb_get_work(WORK_READER); if ( reader->init( reader, job ) ) { hb_error( "Failure to initialise thread '%s'", reader->name ); @@ -1330,9 +1333,9 @@ cleanup: hb_fifo_close( &job->fifo_sync ); hb_fifo_close( &job->fifo_mpeg4 ); - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if( subtitle ) { hb_fifo_close( &subtitle->fifo_in ); @@ -1341,9 +1344,9 @@ cleanup: hb_fifo_close( &subtitle->fifo_out ); } } - for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + for( i = 0; i < hb_list_count( job->list_audio ); i++ ) { - audio = hb_list_item( title->list_audio, i ); + audio = hb_list_item( job->list_audio, i ); if( audio->priv.fifo_in != NULL ) hb_fifo_close( &audio->priv.fifo_in ); if( audio->priv.fifo_raw != NULL ) @@ -1354,13 +1357,22 @@ cleanup: hb_fifo_close( &audio->priv.fifo_out ); } + if( job->list_filter ) + { + for( i = 0; i < hb_list_count( job->list_filter ); i++ ) + { + hb_filter_object_t * filter = hb_list_item( job->list_filter, i ); + hb_fifo_close( &filter->fifo_out ); + } + } + if( job->indepth_scan ) { /* Before closing the title print out our subtitle stats if we need to * find the highest and lowest. */ - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); hb_log( "Subtitle track %d (id 0x%x) '%s': %d hits (%d forced)", subtitle->track, subtitle->id, subtitle->lang, @@ -1415,34 +1427,23 @@ cleanup: hb_log( "No candidate detected during subtitle scan" ); } - for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) { - subtitle = hb_list_item( title->list_subtitle, i ); + subtitle = hb_list_item( job->list_subtitle, i ); if( subtitle->id == subtitle_hit ) { subtitle->config = job->select_subtitle_config; - hb_list_rem( title->list_subtitle, subtitle ); + // Remove from list since we are taking ownership + // of the subtitle. + hb_list_rem( job->list_subtitle, subtitle ); interjob->select_subtitle = subtitle; break; } } } - if( job->list_filter ) - { - for( i = 0; i < hb_list_count( job->list_filter ); i++ ) - { - hb_filter_object_t * filter = hb_list_item( job->list_filter, i ); - hb_fifo_close( &filter->fifo_out ); - hb_filter_close( &filter ); - } - hb_list_close( &job->list_filter ); - } - hb_buffer_pool_free(); - - hb_title_close( &job->title ); - free( job ); + hb_job_close( &job ); } static inline void copy_chapter( hb_buffer_t * dst, hb_buffer_t * src ) |