【问题标题】:How to get the Start Timecode (SMPTE) of a Quicktime-Movie in Objective-C in 64-bit?如何在 64 位的 Objective-C 中获取 Quicktime-Movie 的开始时间码 (SMPTE)?
【发布时间】:2012-08-18 11:29:25
【问题描述】:

我一直在努力解决这个问题。

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

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

我发现了这个: SMPTE TimeCode from Quick Time

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

我在这里疯了。有谁知道这些 API?

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

【问题讨论】:

    标签: objective-c cocoa quicktime


    【解决方案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 稍微复杂一点,上面的代码肯定有一些改进,但它对我有用。

    【讨论】:

    • 无符号字符 *buffer = malloc(length);正在抛出一些错误,试图解决它......但遇到了一些麻烦。
    • 看起来像将其转换为 unsigned char 对我有用。刚刚运行它,它似乎正在工作! @tinmaru,你是我的英雄。
    • 另一个问题,如果你不介意的话。有没有办法确定文件是丢弃还是非丢弃时间码?我正在尝试使用您给我的信息作为起点,但我在查找相关信息时遇到了一些麻烦。
    • 是的,有一些元信息,但并不总是由生成文件的软件填充。我最终计算了样本长度。
    • @mxisaac DF 或 NDF 状态可以使用这个答案读取 [stackoverflow.com/a/12152348/882613] 尽管很奇怪,开始时间码偏移似乎无法使用相同的方法读取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    相关资源
    最近更新 更多