MAC - 用于TRIM的AVAssetReader - 读取订单中的样本

时间:2015-05-29 07:15:47

标签: macos video avfoundation avassetwriter avassetreader

我正在尝试从特定起点和终点的视频文件中读取和写入样本以修剪视频。我正在使用AVAssetReader和AVAssetWriter。

这里使用的逻辑是 -

步骤A:

  • 使用指定的资产创建资产阅读器实例。
  • 根据起点和终点设置阅读器的时间范围。 (例如 - 开始点= 5,结束点= 15,文件长度= 55秒)
  • 开始阅读样本。
  • 获取与我们传入的起点相关的样本的确切时间戳。
  • 存储与起点准确的样本时间戳(可能是5.13左右)。说ta = 5.13
  • 释放阅读器。

步骤B:

  • 使用指定的资产创建新的阅读器实例。
  • 根据起点和终点设置阅读器的时间范围。 (例如 - 开始点= 5,结束点= 15,文件长度= 55秒)
  • 开始阅读样本。
  • 创建一个新的样本缓冲区,其样本时间信息被更改为                                                 (从STEP A取出的样本缓冲区的时间戳t1-ta) - 从0开始写入                                                 (样本缓冲区的时间戳t2-ta从STEP A获取)                                                 (样本缓冲区的时间戳t3-ta从STEP A获取),依此类推到终点。
  • 释放阅读器。

相同的代码示例是:

步骤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;
                }
            }

步骤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;
            }

由于样本的时间戳是按顺序读取的,我们最终会收到错误

“(kFigFormatWriterError_InvalidTimestamp)(解码时间戳小于上一个样本的解码时间戳)”

和时间戳的值是 -

  • 时间戳(以毫秒为单位)= 0.000000
  • 时间戳(以毫秒为单位)= 79.999924
  • 时间戳(以毫秒为单位)= 39.999962
  • 时间戳(以毫秒为单位)= 119.999886
  • 时间戳(以毫秒为单位)= 200.000092
  • 时间戳(以毫秒为单位)= 160.000137
  • 时间戳(以毫秒为单位)= 280.000031
  • 时间戳(以毫秒为单位)= 240.000061
  • 时间戳(以毫秒为单位)= 319.999969
  • 时间戳(以毫秒为单位)= 399.999908
  • 以毫秒为单位的时间戳= 359.999939 等等。

对演示文稿标记进行的任何操作都会导致样本无序读取。

寻找一种方法来克服这种无序读取时间戳的方法。请告诉我们。

提前致谢, 婆

0 个答案:

没有答案