+ if( w->audio->config.out.codec == HB_ACODEC_AC3 )
+ {
+ free( sync->ac3_buf );
+ }
+ else
+ {
+ src_delete( sync->state );
+ }
+
+ hb_lock( pv->common->mutex );
+ if ( --pv->common->ref == 0 )
+ {
+ hb_unlock( pv->common->mutex );
+ hb_lock_close( &pv->common->mutex );
+ free( pv->common );
+ }
+ else
+ {
+ hb_unlock( pv->common->mutex );
+ }
+
+ free( pv );
+ w->private_data = NULL;
+}
+
+int syncAudioInit( hb_work_object_t * w, hb_job_t * job)
+{
+ return 0;
+}
+
+/***********************************************************************
+ * SyncAudio
+ ***********************************************************************
+ *
+ **********************************************************************/
+static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out )
+{
+ hb_work_private_t * pv = w->private_data;
+ hb_job_t * job = pv->job;
+ hb_sync_audio_t * sync = &pv->type.audio;
+ hb_buffer_t * buf;
+ int64_t start;
+
+ *buf_out = NULL;
+ buf = *buf_in;
+ *buf_in = NULL;
+ /* if the next buffer is an eof send it downstream */
+ if ( buf->size <= 0 )
+ {
+ hb_buffer_close( &buf );
+ *buf_out = hb_buffer_init( 0 );
+ return HB_WORK_DONE;
+ }
+
+ /* Wait for start frame if doing point-to-point */
+ hb_lock( pv->common->mutex );
+ while ( !pv->common->start_found )
+ {
+ if ( pv->common->audio_pts_thresh < 0 )
+ {
+ // I would initialize this in hb_sync_init, but
+ // job->pts_to_start can be modified by reader
+ // after hb_sync_init is called.
+ pv->common->audio_pts_thresh = job->pts_to_start;
+ }
+ if ( buf->start < pv->common->audio_pts_thresh )
+ {
+ hb_buffer_close( &buf );
+ hb_unlock( pv->common->mutex );
+ return HB_WORK_OK;
+ }
+ while ( !pv->common->start_found &&
+ buf->start >= pv->common->audio_pts_thresh )
+ {
+ hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
+ }
+ }
+ if ( buf->start < pv->common->audio_pts_thresh )
+ {
+ hb_buffer_close( &buf );
+ hb_unlock( pv->common->mutex );
+ return HB_WORK_OK;
+ }
+ hb_unlock( pv->common->mutex );
+
+ /* Wait till we can determine the initial pts of all streams */
+ if( pv->common->pts_offset == INT64_MIN )
+ {
+ pv->common->first_pts[sync->index+1] = buf->start;
+ hb_lock( pv->common->mutex );
+ while( pv->common->pts_offset == INT64_MIN )
+ {
+ // Full fifos will make us wait forever, so get the
+ // pts offset from the available streams if full
+ if (hb_fifo_is_full(w->fifo_in))
+ {
+ getPtsOffset( w );
+ hb_cond_broadcast( pv->common->next_frame );
+ }
+ else if ( checkPtsOffset( w ) )
+ hb_cond_broadcast( pv->common->next_frame );
+ else
+ hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
+ }
+ hb_unlock( pv->common->mutex );
+ }
+
+ if( job->frame_to_stop && pv->common->count_frames >= job->frame_to_stop )
+ {
+ hb_buffer_close( &buf );
+ *buf_out = hb_buffer_init( 0 );
+ return HB_WORK_DONE;
+ }
+
+ if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
+ {
+ hb_buffer_close( &buf );
+ *buf_out = hb_buffer_init( 0 );
+ return HB_WORK_DONE;
+ }
+
+ hb_lock( pv->common->mutex );
+ start = buf->start - pv->common->audio_passthru_slip;
+ hb_unlock( pv->common->mutex );
+ if ( (int64_t)( start - sync->next_pts ) < 0 )
+ {
+ // audio time went backwards.
+ // If our output clock is more than a half frame ahead of the
+ // input clock drop this frame to move closer to sync.
+ // Otherwise drop frames until the input clock matches the output clock.
+ if ( sync->first_drop || sync->next_start - start > 90*15 )
+ {
+ // Discard data that's in the past.
+ if ( sync->first_drop == 0 )
+ {
+ sync->first_drop = sync->next_pts;
+ }
+ ++sync->drop_count;
+ hb_buffer_close( &buf );
+ return HB_WORK_OK;
+ }
+ sync->next_pts = start;
+ }
+ if ( sync->first_drop )
+ {
+ // we were dropping old data but input buf time is now current
+ hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
+ "(next %"PRId64", current %"PRId64")", w->audio->id,
+ (int)( sync->next_pts - sync->first_drop ) / 90,
+ sync->drop_count, sync->first_drop, sync->next_pts );
+ sync->first_drop = 0;
+ sync->drop_count = 0;
+ sync->next_pts = start;
+ }
+ if ( start - sync->next_pts >= (90 * 70) )
+ {
+ if ( start - sync->next_pts > (90000LL * 60) )
+ {
+ // there's a gap of more than a minute between the last
+ // frame and this. assume we got a corrupted timestamp
+ // and just drop the next buf.
+ hb_log( "sync: %d minute time gap in audio %d - dropping buf"
+ " start %"PRId64", next %"PRId64,
+ (int)((start - sync->next_pts) / (90000*60)),
+ w->audio->id, start, sync->next_pts );
+ hb_buffer_close( &buf );
+ return HB_WORK_OK;
+ }