3

我一直在为此拔头发。

我在这里找到了一些东西,但实际上似乎没有任何效果。而且文档真的很有限。

我在这里试图弄清楚的是如何从时间码轨道中获取 Objective-C 中 Quicktime 电影的开始时间码,并从中获得人类可读的输出。

我发现了这个: 来自 Quick Time 的 SMPTE TimeCode

它在 32 位模式下完美运行。但由于 Quicktime API,它不能在 64 位模式下工作。我需要将其合并到的软件已经并且必须继续运行 64 位。

我在这里失去理智。有人知道这些 API 吗?

最终,这里的目标是找出 Quicktime 的开始时间码,因为它需要在 FCP-X XML 文件中设置偏移量。没有它,视频文件会在没有音频的情况下被引入(或者,真的,它只是滑了很多)。

4

1 回答 1

1

使用AVFoundation框架而不是QuickTime。播放器初始化在文档中有很好的解释:https ://developer.apple.com/library/mac/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html#//apple_ref/doc/uid/TP40010188-CH3 -SW2

一旦您的AVAsset加载到内存中,您可以通过读取时间码轨道的内容(如果存在)来提取第一个样本帧号( timeStampFrame ):

long timeStampFrame = 0;
for (AVAssetTrack * track in [_asset tracks]) {
    if ([[track mediaType] isEqualToString:AVMediaTypeTimecode]) {
        AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:_asset error:nil];
        AVAssetReaderTrackOutput *assetReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:nil]; 
        if ([assetReader canAddOutput:assetReaderOutput]) {
            [assetReader addOutput:assetReaderOutput];
            if ([assetReader startReading] == YES) {
                int count = 0;

                while ( [assetReader status]==AVAssetReaderStatusReading ) {
                    CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer];
                    if (sampleBuffer == NULL) {
                        if ([assetReader status] == AVAssetReaderStatusFailed) 
                            break;
                        else    
                            continue;
                    }
                    count++;

                    CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
                    size_t length = CMBlockBufferGetDataLength(blockBuffer);

                    if (length>0) {
                        unsigned char *buffer = malloc(length);
                        memset(buffer, 0, length);
                        CMBlockBufferCopyDataBytes(blockBuffer, 0, length, buffer);

                        for (int i=0; i<length; i++) {
                            timeStampFrame = (timeStampFrame << 8) + buffer[i];
                        }

                        free(buffer);
                    }

                    CFRelease(sampleBuffer);
                }

                if (count == 0) {
                    NSLog(@"No sample in the timecode track: %@", [assetReader error]);
                }

                NSLog(@"Processed %d sample", count);

            }

        }

        if ([assetReader status] != AVAssetReaderStatusCompleted)
            [assetReader cancelReading];
    }
}

这比QuickTime API稍微复杂一些,上面的代码必须有一些改进,但它对我有用。

于 2012-08-24T04:40:00.040 回答