3

iVidCap プラグインを使用して作成したビデオにオーディオを追加しようとしています。基本的に、この質問とまったく同じです:ビデオ + 生成されたオーディオを AVAssetWriterInput に書き込み、オーディオが吃音します。この記事のコードをベースとして、iVidCap.mm ファイルを自分で変更しようとしましたが、アプリは常に endRecordingSession でクラッシュします。

オーディオに対応するために endRecordingSession をどのように変更する必要があるのか​​ わかりません(元のプラグインはビデオファイルを作成するだけです)。関数は次のとおりです。

- (int) endRecordingSession: (VideoDisposition) action {

NSLog(@"Start endRecordingSession");
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

NSLog(@"Auto released pool");

NSString *filePath;
BOOL success = false;

[videoWriterInput markAsFinished];
NSLog(@"Mark video writer input as finished");
//[audioWriterInput markAsFinished];

// Wait for the video status to become known.
// Is this really doing anything?
int status = videoWriter.status;
while (status == AVAssetWriterStatusUnknown) {
    NSLog(@"Waiting for video to complete...");
    [NSThread sleepForTimeInterval:0.5f];
    status = videoWriter.status;
}

NSLog(@"Video completed");

@synchronized(self) {
    success = [videoWriter finishWriting];
    NSLog(@"Success: %@", success);
    if (!success) {
        // We failed to successfully finalize the video file.
        NSLog(@"finishWriting returned NO");

    } else {
        // The video file was successfully written to the Documents folder.
        filePath = [[self getDocumentsFileURL:videoFileName] path];
        if (action == Save_Video_To_Album) {

            // Move the video to an accessible location on the device.
            NSLog(@"Temporary video filePath=%@", filePath);
            if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath)) {
                NSLog(@"Video IS compatible. Adding it to photo album.");
                UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector(copyToPhotoAlbumCompleteFromVideo: didFinishSavingWithError: contextInfo:), nil);
            } else {
                NSLog(@"Video IS NOT compatible. Could not be added to the photo album.");
                success = NO;
            }
        } else if (action == Discard_Video) {
            NSLog(@"Video cancelled. Removing temporary video file: %@", filePath);
            [self removeFile:filePath];  
        }
    }

    [self cleanupWriter];
}

isRecording = false;

[pool drain];

return success; }

現在、[videoWriter finishWriting] でクラッシュします。[audioWriterInput markAsFinished] を追加してみましたが、その上でクラッシュします。元の投稿者に連絡してみましたが、うまくいったようですが、プライベート メッセージを送信する方法はないようです。

これを機能させる方法やクラッシュする理由について何か提案はありますか? 私はこれを理解するために最善を尽くしましたが、Obj-C にはかなり慣れていません。必要に応じて、残りのコードを投稿できます (その多くは、以前に参照した元の投稿にあります)。

4

1 に答える 1

2

問題は、実際には writeAudioBuffer 関数にある可能性があります。

その投稿からコードをコピーしたが、変更しなかった場合、確かにいくつかの問題が発生します。

次のようなことをする必要があります:

if ( ![self waitForAudioWriterReadiness]) {
    NSLog(@"WARNING: writeAudioBuffer dropped frame after wait limit reached.");
    return 0;
}

OSStatus status;
CMBlockBufferRef bbuf = NULL;
CMSampleBufferRef sbuf = NULL;

size_t buflen = n * nchans * sizeof(float);

CMBlockBufferRef tmp_bbuf = NULL;
status = CMBlockBufferCreateWithMemoryBlock(
                                            kCFAllocatorDefault, 
                                            samples, 
                                            buflen, 
                                            kCFAllocatorDefault, 
                                            NULL, 
                                            0, 
                                            buflen, 
                                            0, 
                                            &tmp_bbuf);

if (status != noErr || !tmp_bbuf) {
    NSLog(@"CMBlockBufferCreateWithMemoryBlock error");
    return -1;
}
// Copy the buffer so that we get a copy of the samples in memory.
// CMBlockBufferCreateWithMemoryBlock does not actually copy the data!
// 
status = CMBlockBufferCreateContiguous(kCFAllocatorDefault, tmp_bbuf, kCFAllocatorDefault, NULL, 0, buflen, kCMBlockBufferAlwaysCopyDataFlag, &bbuf);
//CFRelease(tmp_bbuf); // causes abort?!
if (status != noErr) {
    NSLog(@"CMBlockBufferCreateContiguous error");
    //CFRelease(bbuf);
    return -1;
}


CMTime timestamp = CMTimeMake(sample_position_, 44100);

status = CMAudioSampleBufferCreateWithPacketDescriptions(
    kCFAllocatorDefault, bbuf, TRUE, 0, NULL, audio_fmt_desc_, 1, timestamp, NULL, &sbuf);

sample_position_ += n;
if (status != noErr) {
    NSLog(@"CMSampleBufferCreate error");
    return -1;
}
BOOL r = [audioWriterInput appendSampleBuffer:sbuf];
if (!r) {
    NSLog(@"appendSampleBuffer error");
}
//CFRelease(bbuf); // crashes, don't know why..  Is there a leak here?
//CFRelease(sbuf);

return 0;

メモリ管理に関して、ここでよくわからないことがいくつかあります。

さらに、必ず次を使用してください。

audioWriterInput.expectsMediaDataInRealTime = YES;
于 2012-11-07T09:06:14.237 に答える