mux_data = malloc( sizeof( hb_mux_data_t ) );
audio->mux_data = mux_data;
- mux_data->track = MP4AddAudioTrack( m->file,
+ if( job->acodec & HB_ACODEC_AC3 ||
+ job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
+ {
+ mux_data->track = MP4AddAC3AudioTrack(
+ m->file,
+ job->arate, 1536, MP4_MPEG4_AUDIO_TYPE );
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const u_int8_t*)"Surround", strlen("Surround"));
+ } else {
+ mux_data->track = MP4AddAudioTrack(
+ m->file,
job->arate, 1024, MP4_MPEG4_AUDIO_TYPE );
- MP4SetAudioProfileLevel( m->file, 0x0F );
- MP4SetTrackESConfiguration( m->file, mux_data->track,
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const u_int8_t*)"Stereo", strlen("Stereo"));
+
+ MP4SetAudioProfileLevel( m->file, 0x0F );
+ MP4SetTrackESConfiguration(
+ m->file, mux_data->track,
audio->config.aac.bytes, audio->config.aac.length );
-
+
+ /* Set the correct number of channels for this track */
+ reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown);
+ MP4SetTrackBytesProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.reserved2", reserved2, sizeof(reserved2));
+
+ }
/* Set the language for this track */
/* The language is stored as 5-bit text - 0x60 */
language_code = audio->iso639_2[0] - 0x60; language_code <<= 5;
language_code |= audio->iso639_2[2] - 0x60;
MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code);
- /* Set the correct number of channels for this track */
- reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown);
- MP4SetTrackBytesProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.reserved2", reserved2, sizeof(reserved2));
+ /* Set the audio track alternate group */
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
+
/* If we ever upgrade mpeg4ip, the line above should be replaced with the line below.*/
// MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (u_int16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown));
m->current_chapter = job->chapter_start;
}
+ /* Add encoded-by metadata listing version and build date */
+ char *tool_string;
+ tool_string = (char *)malloc(80);
+ snprintf( tool_string, 80, "HandBrake %s %i", HB_VERSION, HB_BUILD);
+ MP4SetMetadataTool(m->file, tool_string);
+ free(tool_string);
+
return 0;
}
}
free(sample);
m->current_chapter++;
- m->chapter_duration = duration;
+ m->chapter_duration += duration;
}
/* Video */
/* Because we use the audio samplerate as the timescale,
we have to use potentially variable durations so the video
doesn't go out of sync */
- if ( job->vfr )
- {
- duration = ( ( buf->stop * job->arate / 90000 ) - ( buf->start * job->arate / 90000 ) );
- }
- else
- {
- duration = ( buf->stop * job->arate / 90000 ) - m->sum_dur;
- }
+ int64_t bias = ( buf->start * job->arate / 90000 ) - m->sum_dur;
+ duration = ( buf->stop - buf->start ) * job->arate / 90000 + bias;
m->sum_dur += duration;
}
else
// the rendering offset of the first sample.
MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, MP4GetSampleRenderingOffset(m->file,1,1),
MP4GetTrackDuration(m->file, 1), 0);
+ if ( m->job->chapter_markers )
+ {
+ // apply same edit to chapter track to keep it in sync with video
+ MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
+ MP4GetSampleRenderingOffset(m->file,1,1),
+ MP4GetTrackDuration(m->file, m->chapter_track), 0);
+ }
}
MP4Close( m->file );