@@ -162,6 +162,12 @@ public void build(final SharpStream output) throws IOException {
162162 final int [] defaultMediaTime = new int [readers .length ];
163163 final int [] defaultSampleDuration = new int [readers .length ];
164164 final int [] sampleCount = new int [readers .length ];
165+ long [] firstPts = new long [readers .length ];
166+ boolean [] firstPtsSet = new boolean [readers .length ];
167+ boolean minPtsComputed = false ;
168+ long minPts = 0 ;
169+ long [] basePts = new long [readers .length ];
170+ boolean [] basePtsSet = new boolean [readers .length ];
165171
166172 final TablesInfo [] tablesInfo = new TablesInfo [tracks .length ];
167173 for (int i = 0 ; i < tablesInfo .length ; i ++) {
@@ -317,7 +323,7 @@ public void build(final SharpStream output) throws IOException {
317323
318324 for (int i = 0 ; i < readers .length ; i ++) {
319325 if (sampleIndex [i ] < 0 ) {
320- continue ; // track is done
326+ continue ;
321327 }
322328
323329 final long chunkOffset = writeOffset ;
@@ -336,26 +342,62 @@ public void build(final SharpStream output) throws IOException {
336342 if (sample == null ) {
337343 if (tablesInfo [i ].ctts > 0 && sampleExtra [i ] >= 0 ) {
338344 writeEntryArray (tablesInfo [i ].ctts , 1 , sampleCount [i ],
339- sampleExtra [i ]); // flush last entries
345+ sampleExtra [i ]);
340346 outRestore ();
341347 }
342348 sampleIndex [i ] = -1 ;
343349 break ;
344350 }
345351
352+ // Normalize composition timestamps to align audio and video timelines
353+ long pts = sample .info .sampleCompositionTimeOffset ;
354+ if (!firstPtsSet [i ]) {
355+ firstPts [i ] = pts ;
356+ firstPtsSet [i ] = true ;
357+ }
358+
359+ if (!minPtsComputed ) {
360+ boolean allSet = true ;
361+ for (int k = 0 ; k < readers .length ; k ++) {
362+ if (!firstPtsSet [k ]) {
363+ allSet = false ;
364+ break ;
365+ }
366+ }
367+
368+ if (allSet ) {
369+ minPts = firstPts [0 ];
370+ for (int k = 1 ; k < readers .length ; k ++) {
371+ minPts = Math .min (minPts , firstPts [k ]);
372+ }
373+ minPtsComputed = true ;
374+ }
375+ }
376+
346377 sampleIndex [i ]++;
347378
379+ if (!basePtsSet [i ]) {
380+ if (minPtsComputed ) {
381+ basePts [i ] = minPts ;
382+ } else {
383+ basePts [i ] = firstPts [i ];
384+ }
385+ basePtsSet [i ] = true ;
386+ }
387+
388+ int correctedOffset = (int ) (pts - basePts [i ]);
348389 if (tablesInfo [i ].ctts > 0 ) {
349- if (sample . info . sampleCompositionTimeOffset == sampleExtra [i ]) {
390+ if (correctedOffset == sampleExtra [i ]) {
350391 sampleCount [i ]++;
351392 } else {
352393 if (sampleExtra [i ] >= 0 ) {
353- tablesInfo [i ].ctts = writeEntryArray (tablesInfo [i ].ctts , 2 ,
354- sampleCount [i ], sampleExtra [i ]);
394+ tablesInfo [i ].ctts = writeEntryArray (
395+ tablesInfo [i ].ctts , 2 , sampleCount [i ], sampleExtra [i ]
396+ );
355397 outRestore ();
356398 }
357399 sampleCount [i ] = 1 ;
358- sampleExtra [i ] = sample . info . sampleCompositionTimeOffset ;
400+ sampleExtra [i ] = correctedOffset ;
359401 }
360402 }
361403
0 commit comments