summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/bd.c4
-rw-r--r--libhb/common.c742
-rw-r--r--libhb/common.h101
-rw-r--r--libhb/decavcodec.c2
-rw-r--r--libhb/decmetadata.c114
-rw-r--r--libhb/decmpeg2.c8
-rw-r--r--libhb/decsrtsub.c5
-rw-r--r--libhb/dvd.c4
-rw-r--r--libhb/dvdnav.c4
-rw-r--r--libhb/hb.c326
-rw-r--r--libhb/hb.h18
-rw-r--r--libhb/internal.h4
-rw-r--r--libhb/muxcommon.c9
-rw-r--r--libhb/muxmkv.c72
-rw-r--r--libhb/muxmp4.c73
-rw-r--r--libhb/reader.c20
-rw-r--r--libhb/rendersub.c6
-rw-r--r--libhb/scan.c104
-rw-r--r--libhb/stream.c100
-rw-r--r--libhb/sync.c7
-rw-r--r--libhb/work.c113
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 )