// bias to keep render offsets in ctts atom positive (set up by encx264)
int64_t init_delay;
- uint64_t sum_sub_duration; // sum of subtitle frame durations so far
-
/* Chapter state information for muxing */
MP4TrackId chapter_track;
int current_chapter;
struct hb_mux_data_s
{
- MP4TrackId track;
- uint8_t subtitle;
- int sub_format;
+ MP4TrackId track;
+ uint8_t subtitle;
+ int sub_format;
+
+ uint64_t sum_dur; // sum of the frame durations so far
};
/* Tune video track chunk duration.
hb_audio_t * audio;
hb_mux_data_t * mux_data;
int i;
+ int subtitle_default;
/* Flags for enabling/disabling tracks in an MP4. */
typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8} track_header_flags;
}
+ // Quicktime requires that at least one subtitle is enabled,
+ // else it doesn't show any of the subtitles.
+ // So check to see if any of the subtitles are flagged to be
+ // the defualt. The default will the the enabled track, else
+ // enable the first track.
+ subtitle_default = 0;
for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, i );
if( subtitle && subtitle->format == TEXTSUB &&
- subtitle->dest == PASSTHRUSUB )
+ subtitle->config.dest == PASSTHRUSUB )
{
+ if ( subtitle->config.default_track )
+ subtitle_default = 1;
+ }
+ }
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
+ {
+ hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, i );
+
+ if( subtitle && subtitle->format == TEXTSUB &&
+ subtitle->config.dest == PASSTHRUSUB )
+ {
+ uint64_t width, height = 60;
+ if( job->anamorphic.mode )
+ width = job->width * ( (float) job->anamorphic.par_width / job->anamorphic.par_height );
+ else
+ width = job->width;
+
mux_data = calloc(1, sizeof( hb_mux_data_t ) );
subtitle->mux_data = mux_data;
mux_data->subtitle = 1;
mux_data->sub_format = subtitle->format;
- mux_data->track = MP4AddSubtitleTrack( m->file, 1 );
+ mux_data->track = MP4AddSubtitleTrack( m->file, 90000, width, height );
MP4SetTrackLanguage(m->file, mux_data->track, subtitle->iso639_2);
MP4TuneTrackDurationPerChunk( m, mux_data->track );
const uint8_t textColor[4] = { 255,255,255,255 };
- uint64_t subHeight = 60;
MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 2);
- MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width);
- MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.height", subHeight);
-
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.dataReferenceIndex", 1);
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.horizontalJustification", 1);
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.verticalJustification", 0);
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.bgColorAlpha", 255);
- MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.defTextBoxBottom", subHeight);
- MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.defTextBoxRight", job->width);
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.defTextBoxBottom", height);
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.defTextBoxRight", width);
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.fontID", 1);
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.tx3g.fontSize", 24);
MP4GetTrackBytesProperty(m->file, mux_data->track, "tkhd.matrix", &val, &size);
memcpy(nval, val, size);
- const uint32_t ytranslation = (job->height - subHeight) * 0x10000;
+ const uint32_t ytranslation = (job->height - height) * 0x10000;
#ifdef WORDS_BIGENDIAN
ptr32[7] = ytranslation;
#endif
MP4SetTrackBytesProperty(m->file, mux_data->track, "tkhd.matrix", nval, size);
+ if ( !subtitle_default || subtitle->config.default_track ) {
+ /* Enable the default subtitle track */
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
+ subtitle_default = 1;
+ }
+ else
+ {
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
+ }
}
}
if( mux_data->sub_format == TEXTSUB )
{
/* Write an empty sample */
- if ( m->sum_sub_duration < buf->start )
+ if ( mux_data->sum_dur < buf->start )
{
uint8_t empty[2] = {0,0};
if( !MP4WriteSample( m->file,
mux_data->track,
empty,
2,
- buf->start - m->sum_sub_duration,
+ buf->start - mux_data->sum_dur,
0,
1 ))
{
hb_error("Failed to write to output file, disk full?");
*job->die = 1;
}
- hb_log("Subtitle not due yet, adding delay of %lld", buf->start - m->sum_sub_duration);
- m->sum_sub_duration += buf->start - m->sum_sub_duration;
+ mux_data->sum_dur += buf->start - mux_data->sum_dur;
}
/* Write the subtitle sample */
if( !MP4WriteSample( m->file,
mux_data->track,
buffer,
- buf->size,
+ buf->size + 2,
buf->stop - buf->start,
0,
1 ))
*job->die = 1;
}
- m->sum_sub_duration += (buf->stop - buf->start);
- hb_log("MuxMP4:Sub:%lld:%lld:%lld: %s", buf->start, buf->stop,
+ mux_data->sum_dur += (buf->stop - buf->start);
+ hb_deep_log(3, "MuxMP4:Sub:%fs:%lld:%lld:%lld: %s", (float)buf->start / 90000, buf->start, buf->stop,
(buf->stop - buf->start), buf->data);
- hb_log("MuxMP4:Total time elapsed:%lld", m->sum_sub_duration);
+ hb_deep_log(3, "MuxMP4:Total time elapsed:%lld", mux_data->sum_dur);
}
}
else
MP4TagsFetch( tags, m->file );
/* populate */
- MP4TagsSetName( tags, md->name );
- MP4TagsSetArtist( tags, md->artist );
- MP4TagsSetComposer( tags, md->composer );
- MP4TagsSetComments( tags, md->comment );
- MP4TagsSetReleaseDate( tags, md->release_date );
- MP4TagsSetAlbum( tags, md->album );
- MP4TagsSetGenre( tags, md->genre );
+ if( strlen( md->name ))
+ MP4TagsSetName( tags, md->name );
+ if( strlen( md->artist ))
+ MP4TagsSetArtist( tags, md->artist );
+ if( strlen( md->composer ))
+ MP4TagsSetComposer( tags, md->composer );
+ if( strlen( md->comment ))
+ MP4TagsSetComments( tags, md->comment );
+ if( strlen( md->release_date ))
+ MP4TagsSetReleaseDate( tags, md->release_date );
+ if( strlen( md->album ))
+ MP4TagsSetAlbum( tags, md->album );
+ if( strlen( md->genre ))
+ MP4TagsSetGenre( tags, md->genre );
if( md->coverart )
{