3

我有一部电影有两个视频轨道。我需要从交错的两个轨道中读取帧 - 即从轨道 1 读取一帧,然后从轨道 2 读取一帧,然后从轨道 1 读取,依此类推。我正在使用带有两个 AVAssetReaders 的 AVAsset 来读取帧并且它可以工作;但是,如果我取消分配所有内容并再次尝试,则 copyNextSampleBuffer 在第一帧返回 null,错误为 -11829(无法打开)。如果我尝试单轨电影,或者我尝试从同一部电影中读取单轨,则不会发生这种情况。

这是我的精简代码:

NSURL *url = /* url to movie */;
NSError *localError = nil;
AVAssetReader *assetReader[2];
AVAssetReaderOutput *assetReaderOutput[2];
NSDictionary *assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
NSDictionary *decompressionVideoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                                [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey,
                                                [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey,
                                                nil];
for (int loop = 0; loop < 2; ++loop)
{
    AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
    float durationInSeconds = CMTimeGetSeconds(asset.duration);
    NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    NSUInteger numTracks = [videoTracks count];
    float framesPerSecond = [videoTracks[0] nominalFrameRate];
    int numFrames = (int)(durationInSeconds * framesPerSecond);
    for (NSUInteger trackNum = 0; trackNum < numTracks; ++trackNum)
    {
        assetReader[trackNum] = [[AVAssetReader alloc] initWithAsset:asset error:&localError];
        assetReaderOutput[trackNum] = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTracks[trackNum] outputSettings:decompressionVideoSettings];
        [assetReader[trackNum] addOutput:assetReaderOutput[trackNum]];
        [assetReader[trackNum] startReading];
    }

    for (int frameNum = 0; frameNum < numFrames; ++frameNum)
    {
        for (int trackNum = 0; trackNum < numTracks; ++trackNum)
        {
            CMSampleBufferRef sampleBuffer = [assetReaderOutput[trackNum] copyNextSampleBuffer];
            if (sampleBuffer == NULL)
            {
                NSError *error = [assetReader[trackNum] error];
                /* Handle error */
            }
            else
            {
                CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
                if (imageBuffer && (CFGetTypeID(imageBuffer) == CVPixelBufferGetTypeID()))
                {
                    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)imageBuffer;
                    CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
                    void* ptr = CVPixelBufferGetBaseAddress(pixelBuffer);
                    CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
                    /* Do something with ptr */
                }
                CFRelease(sampleBuffer);
                sampleBuffer = NULL;
            }
        }
    }

    [asset release];
    asset = nil;
    for (int trackNum = 0; trackNum < numTracks; ++trackNum)
    {
        [assetReader[trackNum] release];
        assetReader[trackNum] = nil;
        [assetReaderOutput[trackNum] release];
        assetReaderOutput[trackNum] = nil;
    }

    int userInput;
    scanf("%i", &userInput);
}

所以在外循环的第二次迭代中,我得到 了第一条轨道第一帧上的Handle 错误代码。为了清楚起见,例如,如果我替换该行,则不会发生这种情况

NSUInteger numTracks = [videoTracks count];

NSUInteger numTracks = 1;

有任何想法吗?这可能与这个(尚未回答的)问题有关。

4

0 回答 0