3

以下のコードを使用して、画像をビデオに書き込みました

-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size
{
    NSLog(@"Write Started");

    NSError *error = nil;

    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                                  [NSURL fileURLWithPath:path] fileType:AVFileTypeMPEG4
                                                              error:&error];
    NSParameterAssert(videoWriter);

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   AVVideoCodecH264, AVVideoCodecKey,
                                   [NSNumber numberWithInt:size.width], AVVideoWidthKey,
                                   [NSNumber numberWithInt:size.height], AVVideoHeightKey,
                                   nil];

    AVAssetWriterInput* videoWriterInput = [[AVAssetWriterInput
                                             assetWriterInputWithMediaType:AVMediaTypeVideo
                                             outputSettings:videoSettings] retain];


    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
                                                     assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
                                                     sourcePixelBufferAttributes:nil];

    NSParameterAssert(videoWriterInput);
    NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
    videoWriterInput.expectsMediaDataInRealTime = YES;
    [videoWriter addInput:videoWriterInput];

    //Start a session:
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];

    CVPixelBufferRef buffer = NULL;

    //convert uiimage to CGImage.

    int frameCount = 16;
    int kRecordingFPS = 30;
    UIImage * im = [UIImage imageNamed:@"IMG_0103.JPG"];

    NSArray * imageArray = [[NSArray alloc]initWithObjects:im,im,im,im,im,im,im,im,im,im,im,im,im,im,im,im, nil];

    for(UIImage * img in imageArray)
    {
        buffer = [self pixelBufferFromCGImage:[img CGImage] andSize:size];

        BOOL append_ok = NO;
        int j = 0;
        while (!append_ok && j < 30)
        {
            if (adaptor.assetWriterInput.readyForMoreMediaData)
            {
                printf("appending %d attemp %d\n", frameCount, j);

                CMTime frameTime = CMTimeMake(frameCount,(int32_t) kRecordingFPS);
                append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];

                if(buffer)
                    CVBufferRelease(buffer);
                [NSThread sleepForTimeInterval:0.05];
            }
            else
            {
                printf("adaptor not ready %d, %d\n", frameCount, j);
                [NSThread sleepForTimeInterval:0.1];
            }
            j++;
        }
        if (!append_ok) {
            printf("error appending image %d times %d\n", frameCount, j);
        }
        frameCount++;
    }


    //Finish the session:
    [videoWriterInput markAsFinished];
    [videoWriter finishWriting];
    NSLog(@"Write Ended");
    [videoWriterInput release];
    [videoWriter release];
    [imageArray release];
}

最初は機能しますが、コードを 2,3 回以上実行すると、次のように報告されました。

!appending 0 0-0 attemp 0
!appending 0 0-0 attemp 1
My App(11385,0xb0103000) malloc: *** error for object 0x9ab4270: double free
*** set a breakpoint in malloc_error_break to debug
!appending 0 0-0 attemp 2
My App(11385,0xb0103000) malloc: *** error for object 0x9ab4270: double free
*** set a breakpoint in malloc_error_break to debug
!appending 0 0-0 attemp 3

それがクラッシュを引き起こしたとき

原因を探るが結果が出ない

あなたのコメント歓迎

4

2 に答える 2

10

[NSThread sleepForTimeInterval:0.1] を使用する代わりに; while(!adaptor.assetWriterInput.readyForMoreMediaData) {}を使用

多くの場合、readyForMoreMediaDataは 0.1 時間間隔で YES に設定されることはありません。

また、appendPixelBuffer:withPresentationTime:メソッドによって占有されているメモリを解放してみてください。実際には、このメソッドは正常に実行できなくなります。

于 2012-11-23T05:44:51.847 に答える
1

作成ルールで説明されているように、CFRelease() でバッファを解放する必要があります。

if ([assetWriterInput isReadyForMoreMediaData]) {
    CVPixelBufferRef pixelBuffer = [self newPixelBufferFromCGImage:image.CGImage];
    CMTime frameTime = CMTimeMake(frameCount,(int32_t) kRecordingFPS);
    if (![adaptor appendPixelBuffer:pixelBuffer withPresentationTime:frameTime]) {
        NSError *error = [videoWriter error];
        NSLog(@"failed to append sbuf: %@", error);
    }
    CFRelease(pixelBuffer);
}
于 2013-11-30T22:51:59.287 に答える