1

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

这里使用的逻辑是 -

步骤一:

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

步骤 B:

  • 使用指定的资产创建一个新的阅读器实例。
  • 根据起点和终点设置阅读器的时间范围。(例如 - 起点 = 5,终点 = 15,文件长度 = 55 秒)
  • 开始阅读样本。
  • 创建一个新的样本缓冲区,其样本时序信息更改为(从步骤 A 获取的样本缓冲区的时间戳 t1-ta) - 这从 0 开始写入(从步骤 A 获取的样本缓冲区的时间戳 t2- ta)(样本缓冲区的时间戳 t3 - ta 从 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;
                }
            }

步骤 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 等等

对演示印章进行的任何操作都会导致样本的无序读取。

寻找一种方法来克服这种无序读取时间戳的问题。请告知。

提前致谢, 占巴

4

0 回答 0