1

I am trying to read and write the samples from a video file at a specific start point and end point for trimming a video. I am using AVAssetReader and AVAssetWriter.

The logic used here is -

STEP A:

  • Create asset reader instance with the specified asset.
  • Set the time range to the reader as per the start and end points. ( Say for example - start point = 5, end point = 15, file length = 55 sec )
  • Start reading the samples.
  • Get the sample's exact time stamp with respect to start point that we have passed in.
  • Store the time stamp of the sample that is accurate with the start point.( could be 5.13 or so ). Say ta = 5.13
  • Release the reader.

STEP B:

  • Create a new reader instance with the specified asset.
  • Set the time range to the reader as per the start and end points. ( Say for example - start point = 5, end point = 15, file length = 55 sec )
  • Start reading the samples.
  • Create a new sample buffer with sample timing info altered as ( sample buffer's time stamp t1- ta fetched from STEP A ) - This starts to write from 0 ( sample buffer's time stamp t2- ta fetched from STEP A ) ( sample buffer's time stamp t3- ta fetched from STEP A ) and so on till end point.
  • Release the reader.

The code sample for the same is:

STEP A:

while ([assetWriterInput isReadyForMoreMediaData] )
            {
                CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
                if (sampleBuffer != NULL)
                {
                    CMTime originalTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
                    float time = CMTimeGetSeconds( originalTime );

                   // This is where we store the time stamp 
                    fTimeTange = time;
                    [HelpMethods setCorrectEditTime:fTimeTange]; // This is stored globally 

                    // This is to release the readers and writers and start a fresh call with the stored time stamp ta
                    [delegate resetTimeRange];
                    return;
                }
            }

STEP B:

while ([assetWriterInput isReadyForMoreMediaData] ) 
         {
            CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
            if (sampleBuffer != NULL)
            {
                CMSampleBufferRef finalBuffer = sampleBuffer;
                CMSampleBufferRef newSampleBuffer;
                CMSampleTimingInfo sampleTimingInfo;

                CMTime cmm1 = CMSampleBufferGetOutputDuration(sampleBuffer);

                CMTime originalTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
                float time = CMTimeGetSeconds( originalTime );

                // This is a helper method to get the stored ta at STEP A
                fTimeTange = [HelpMethods getCorrectEditTime];

                sampleTimingInfo.duration = cmm1;
                float milliseconds = (time - fTimeTange) * 600;

                NSLog( @"Timestamp in  milliseconds = %f", milliseconds );

                sampleTimingInfo.presentationTimeStamp = CMTimeMake(milliseconds, 600);
                sampleTimingInfo.decodeTimeStamp = kCMTimeInvalid;

                CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault,
                                                      sampleBuffer,
                                                      1,
                                                      &sampleTimingInfo,
                                                      &newSampleBuffer);
                finalBuffer = newSampleBuffer;


                BOOL success = YES;
                success  = [assetWriterInput appendSampleBuffer:finalBuffer];


                CFRelease(sampleBuffer);
                sampleBuffer = NULL;
            }

Since the time stamps of the samples are read in out of order fashion, we end up getting an error saying

"(kFigFormatWriterError_InvalidTimestamp) (decode timestamp is less than previous sample's decode timestamp)"

and the values of time stamps are -

  • Timestamp in milliseconds = 0.000000
  • Timestamp in milliseconds = 79.999924
  • Timestamp in milliseconds = 39.999962
  • Timestamp in milliseconds = 119.999886
  • Timestamp in milliseconds = 200.000092
  • Timestamp in milliseconds = 160.000137
  • Timestamp in milliseconds = 280.000031
  • Timestamp in milliseconds = 240.000061
  • Timestamp in milliseconds = 319.999969
  • Timestamp in milliseconds = 399.999908
  • Timestamp in milliseconds = 359.999939 and so on

Any manipulation done to the presentation stamps results in out of order reading of samples.

Looking out a way to overcome this out of order reading of timestamps. Please let know.

Thanks in advance, Champa

ForeverNoob
  • 141
  • 1
  • 14
Champa M.S
  • 11
  • 1
  • 1
  • Case 1: If the sample buffer is not manipulated with the new timing info using appendSampleBuffer and used as it is, then even though the samples read are OUT of ORDER, the final video turns out to be the right one. Case 2: If the presentation stamp is manipulated as shown above using sampleTimingInfo, then there is problem. – Champa M.S Jun 01 '15 at 06:43
  • Hello, Has anybody faced the same problem and any solution with which this out of order can be avoided or handled ?????? Any suggestion would be helpful. – Champa M.S Jun 17 '15 at 05:07
  • Can you let me know how you are able to solve this issue. I am facing similar issue here .. – Dinesh Sep 03 '15 at 09:38
  • I'm also really interested in the solution to this – petenelson Sep 04 '15 at 08:56

0 Answers0